0

我正在使用 Django 框架开发票务系统。我想实现一个功能,可以通过电子邮件创建票证,到目前为止收件人电子邮件与用户相关联。

我使用 mailgun 创建了一个将邮件数据重定向到 URL 的路由。

除了附件之外,我已经能够成功处理邮件内容,我认为这是因为我没有设置上传文件时必需的 enctype 属性。表单未验证。

是否可以在银行设置 enctype="multipart/form-data" ?

模型.py

from django.db import models
from .utils import *
from django.db.models.signals import pre_save

class Ticket(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    subject = models.CharField(max_length=50, blank=False, null=False)
    message = models.TextField()
    task = models.ForeignKey(Task, on_delete=models.CASCADE, null=True, blank=True)
    status = models.CharField(max_length=50, choices=STATUS_CHOICES, default='open')
    request_time = models.DateTimeField(auto_now_add=True)
    response_time = models.DateTimeField(auto_now=True)
    priority = models.CharField(max_length=50, choices=PRIORITY_CHOICES, default='mid')
    is_active = models.BooleanField(_('active'), default=True)

    objects = GeneralManager()

    def __str__(self):
        return self.subject

    def get_absolute_url(self):
        return reverse('ticket_detail', kwargs={'pk': self.pk})

def req_ticket_create_update_receiver(sender, instance, *args, **kwargs):
    # reciever function for ticket model
    from_email = config('from_email')
    if Ticket.objects.filter(id=instance.id).exists():
        if instance.status == 'close':
            subject = f'Ticket With ID {instance.id} Has Been Closed'
            message = f'Hello {instance.user.get_short_name()}, \nYour ticket with ID {instance.id} has been closed. We hope the resolution to this trouble was up to satisfaction. \n\nRegards.'
            instance.user.email_user(subject=subject, message=message, from_email=from_email, fail_silently=True,)
        elif instance.status == 'pending':
            subject = f'Work Has Begun On Your Ticket With ID {instance.id}'
            message = f'Hello {instance.user.get_short_name()}, \nWe\'ve started working on your ticket with ID {instance.id}. \n\nRegards.'
            instance.user.email_user(subject=subject, message=message, from_email=from_email, fail_silently=True,)
    else:
        subject = f'Ticket With ID {instance.id} Has Been Issued'
        message = f'Hello {instance.user.get_short_name()}, \nYour ticket with ID {instance.id} has been created. We have started working on it & you\'ll get a feedback as soon as possible. \n\nRegards.'
        instance.user.email_user(subject=subject, message=message, from_email=from_email, fail_silently=True,)

pre_save.connect(req_ticket_create_update_receiver, sender=Ticket, weak=False)


class Attachment(models.Model):
    ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE)
    file = models.FileField(upload_to=upload_image_path, null=True, blank=True)
    date = models.DateTimeField(auto_now_add=True)

实用程序.py

import os
import random

def get_filename_ext(filepath):
    """Split file path into name & extension"""
    base_name   = os.path.basename(filepath)
    name, ext   = os.path.splitext(base_name)
    return name, ext

def upload_image_path(instance, filename):
    """Create New File Name"""
    new_filename    = random.randint(1, 3910209312)
    name, ext       = get_filename_ext(filename)
    final_filename  = f"{new_filename}{ext}"
    return f'tickets/{new_filename}/{final_filename}'

表格.py

from .models import Attachment
class AttachmentForm(ModelForm):
    class Meta:
        model = Attachment
        fields = ['ticket', 'file']

项目 urls.py

from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
from django.urls import path, include
from django.views.generic import TemplateView

urlpatterns = [
    path('', include('Ticket.urls')),
    path('', include('Auth.urls')),
    path('', TemplateView.as_view(template_name='dashboard.html'), name='home'),
    path('admin/', admin.site.urls),
]

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

应用程序 urls.py

from django.contrib.auth import views as auth_views
from django.urls import path
from .views import *

urlpatterns = [
    path('consume/email/', recieve_incoming_mail, name='consume-email'),

    path('tickets/<int:pk>/del/', ticket_del_view, name='ticket_delete'),
    path('tickets/search/', SearchView.as_view(), name='ticket_search'),
    path('tickets/create/', TicketCreateView.as_view(), name='ticket_create'),
    path('tickets/<int:pk>/edit/', TicketUpdateView.as_view(), name='ticket_update'),
    path('tickets/<int:pk>/', TicketDetailView.as_view(), name='ticket_detail'),
    path('tickets/', TicketListView.as_view(), name='ticket_list'),

    path('company/<int:pk>/del/', company_del_view, name='company_delete'),
    path('company/create/', CompanyCreateView.as_view(), name='company_create'),
    path('company/<int:pk>/edit/', CompanyUpdateView.as_view(), name='company_update'),
    path('company/<int:pk>/', CompanyDetailView.as_view(), name='company_detail'),
    path('company/', CompanyListView.as_view(), name='company_list'),

    path('projects/<int:pk>/del/', project_del_view, name='project_delete'),
    path('projects/create/', ProjectCreateView.as_view(), name='project_create'),
    path('projects/<int:pk>/edit/', ProjectUpdateView.as_view(), name='project_update'),
    path('projects/<int:pk>/', ProjectDetailView.as_view(), name='project_detail'),
    path('projects/', ProjectListView.as_view(), name='project_list'),

    path('tasks/<int:pk>/del/', task_del_view, name='task_delete'),
    path('tasks/create/', TaskCreateView.as_view(), name='task_create'),
    path('tasks/<int:pk>/edit/', TaskUpdateView.as_view(), name='task_update'),
    path('tasks/<int:pk>/', TaskDetailView.as_view(), name='task_detail'),
    path('tasks/', TaskListView.as_view(), name='task_list'),
]

视图.py

from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.http import QueryDict

@csrf_exempt
def recieve_incoming_mail(request):
    '''
    Consumes incoming mail
    Creates a new ticket if sender is user.
    '''
    if request.method == 'POST':
        # reference mime
        print(request.POST, request.FILES)
        subject   = request.POST.get('subject', '')
        body_plain = request.POST.get('body-plain', '')
        sender = request.POST.get('sender', '')

        # check if user exist before issuing ticket from incoming email
        if User.objects.filter(email=sender).active().exists():
            user = User.objects.get(email=sender)
            ticket = Ticket.objects.create(user=user, subject=subject,
                message=body_plain
                )
            if ticket and request.FILES:
                print('About to start saving files!!!')
                dict={'ticket':ticket}
                data = QueryDict('', mutable=True)
                data.update(dict)
                print(data)
                form = AttachmentForm(data=data, files=request.FILES)
                if form.is_valid():
                    print('Saving file!!!')
                    form.save()
            print('Incoming Email Consumed!!!!!')
        else:
            # send email to sender to create an Account
            subject = 'Create an account'
            message = 'Hello,\nYou tried to create a ticket for resolution but your email doesnt exist in our database.\nCreate an account via the link below & resend the mail.\nhttps://tcsys.herokuapp.com/user/create/\nRegards'
            send_mail(subject=subject, message=message,
            from_email= config('from_email'),
            recipient_list=[from_email])

    # Mailgun needs a 2** http response to know the process was successful
    # unless mg will resend in 5mins
    return HttpResponse('OK')
4

1 回答 1

0
  1. pathlib.Path 很棒!

实用程序.py

import random
from pathlib import Path

def get_filename_ext(filepath):
    """Split file path into name & extension"""
    p   = Path(filepath)
    name, ext   = p.stem, p.suffix
    return name, ext

def upload_image_path(instance, filename):
    """Create New File Name"""
    new_filename    = random.randint(1, 3910209312)
    final_filename  = f"{new_filename}{Path(filename).suffix}"
    return f'tickets/{new_filename}/{final_filename}'
  1. 在后端设置 html 内容的示例

post.html

<form method="post">{% csrf_token %}
{{ form.as_p }}
</form>

视图.py

import re
from pathlib import Path
from django.http import HttpResonse
from django.template import loader
from django.template import Template
from django.template import Context

def view1(request):
    form_class = PostForm
    if request.method == 'POST':
        form = form_class(request.POST, request.FILES)
        form.save()
        return redirect('/')
    else:
        form = form_class()
    template = loader.get_template('post.html')
    html = Path(str(template.origin)).read_text()
    patt = re.compile(r'(<form )(.*?)>')
    t = 'enctype="multipart/form-data"'
    if (m := patt.search(html)) and t not in m.group(2):  # python3.8 syntax
        html = patt.sub(rf'\1\2 {t}>', html)
    template = Template(html)
    return HttpResponse(template.render(Context({'form': form})))
于 2019-08-29T08:47:46.263 回答