Использование действий администратора Django для массовой рассылки писем

Я ищу способ отправлять массовые электронные письма пользователям из действия администратора Django. Это то, что у меня есть до сих пор:

class MyUserAdmin(UserAdmin):
    list_display = ['username', 'email', 'first_name', 'last_name', 'is_active', staff]
    list_filter = ['groups', 'is_staff', 'is_superuser', 'is_active']
    actions = ['send_EMAIL']


    def send_EMAIL(self, request, queryset):
        from django.core.mail import send_mail
        for i in queryset:
            if i.email:
                send_mail('Subject here', 'Here is the message.', '[email protected]',[i.email], fail_silently=False)
            else:
        self.message_user(request, "Mail sent successfully ") 
    send_EMAIL.short_description = "Send an email to selected users"

Это хорошо, но! Я должен жестко кодировать фактическое сообщение каждый раз. Что, если бы я мог сделать его динамическим? Вместо того, чтобы изменять сообщение из admin.py каждый раз, когда мне нужно отправить массовую рассылку, почему бы не создать промежуточную страницу действий администратора Django с пустым полем ввода текста, где я могу написать новое сообщение для отправки каждый раз?

Как это может быть сделано? Я ищу хорошо подробный ответ, который не является открытым и общим.


person deadlock    schedule 04.09.2013    source источник


Ответы (2)


Ты на правильном пути. Вот моя реализация действия администратора django, которое позволяет вам написать сообщение выбранным пользователям. (Я знаю, что это очень поздно, но может помочь кому-то еще).

функция send_email:

def send_email(self, request, queryset):
    form = SendEmailForm(initial={'users': queryset})
    return render(request, 'users/send_email.html', {'form': form})

шаблон send_email.html (я позаимствовал разметку из представления подтверждения удаления django, для этого вы можете сделать что-то другое):

{% extends "admin/base_site.html" %}
{% load i18n admin_urls static %}


{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} delete-confirmation{% endblock %}

{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
&rsaquo; <a href="{% url 'admin:app_list' app_label='users' %}">{% trans "Users" %}</a>
&rsaquo; <a href="{% url 'admin:users_user_changelist' %}">{% trans "Users" %}</a>
&rsaquo; <span>Send email</span>
</div>
{% endblock %}

{% block content %}
<p>{% blocktrans %}Write your message here{% endblocktrans %}</p>
<form method="POST" action="{% url 'users:email' %}">{% csrf_token %}
    <div>
        <div>
            <p>{{ form.users.errors }}</p>
            <p>{{ form.users.label_tag }}</p>
            <p>
                {% for user in form.users.initial %}
                    {{ user.email }}{% if not forloop.last %},&nbsp;{% endif %}
                {% endfor %}
            </p>
            <select name="users" multiple style="display: none">
                {% for user in form.users.initial %}
                    <option value="{{ user.id }}" selected>{{ user }}</option>
                {% endfor %}
            </select>
        </div>
        <div>
            <p>{{ form.subject.errors }}</p>
            <p>{{ form.subject.label_tag }}</p>
            <p>{{ form.subject }}</p>
        </div>
        <div>
            <p>{{ form.message.errors }}</p>
            <p>{{ form.message.label_tag }}</p>
            <p>{{ form.message }}</p>
        </div>
        <input type="submit" value="{% trans 'Send message' %}" />
        <a href="{% url 'admin:users_user_changelist' %}" class="button cancel-link">{% trans "No, take me back" %}</a>
    </div>
</form>
{% endblock %}

отправить класс формы электронной почты:

class SendEmailForm(forms.Form):
    subject = forms.CharField(
        widget=forms.TextInput(attrs={'placeholder': _('Subject')}))
    message = forms.CharField(widget=forms.Textarea)
    users = forms.ModelMultipleChoiceField(label="To",
                                           queryset=User.objects.all(),
                                           widget=forms.SelectMultiple())

И, наконец, представление отправки электронной почты + настройка URL:

# url pattern
url(
    regex=r'^email-users/$',
    view=views.SendUserEmails.as_view(),
    name='email'
),


# SendUserEmails view class
class SendUserEmails(IsStaff, FormView):
    template_name = 'users/send_email.html'
    form_class = SendEmailForm
    success_url = reverse_lazy('admin:users_user_changelist')

    def form_valid(self, form):
        users = form.cleaned_data['users']
        subject = form.cleaned_data['subject']
        message = form.cleaned_data['message']
        email_users.delay(users, subject, message)
        user_message = '{0} users emailed successfully!'.format(form.cleaned_data['users'].count())
        messages.success(self.request, user_message)
        return super(SendUserEmails, self).form_valid(form)

Эта реализация работала нормально для меня. Вот как выглядит промежуточный вид:

Пользователи электронной почты

Возможно, вам придется изменить пару вещей в шаблоне, где я создаю навигационные цепочки или обратный URL-адрес для представления, если у вас нет приложения с именем users или модели с именем User.

person manncito    schedule 27.01.2017

Вам нужно написать собственное представление администратора в вашем классе администратора, которое будет отображать форму, которую вы хотите. Чтобы определить URL-адрес для этого представления, вам необходимо перезаписать метод ModelAdmin.get_urls(). Документация Django кратко упоминает об этом, но для более подробной информации предлагаю Вам заглянуть в исходный код Django Admin (файл django/contrib/admin/sites.py).

person HankMoody    schedule 04.09.2013