开发者

Admin inlines linked indirectly by a shared UUID instead of by foreign key

开发者 https://www.devze.com 2023-04-11 01:50 出处:网络
I have posts and attachments. The source of my problem is that I would like it to be possible to create attachments before creating the post they are attached to (because the user uses the fancy Ajax

I have posts and attachments. The source of my problem is that I would like it to be possible to create attachments before creating the post they are attached to (because the user uses the fancy Ajax upload widget to upload the attachment before filling out the details of the post). The solution I have arrived at is to give each post a UUID. The UUID is generated when the post's modelform is instantiated (i.e., before creating the post). When attachments are uploaded, they are associated with this UUID. Before I pose my question, here is a sketch of the code in order to show more开发者_开发知识库 precisely what is going on:

 # models.py

 import uuid
 from django.db import models

 class Post(models.Model):
      nonce = models.CharField(max_length=36)

 class FooPost(Post):
      body = models.TextField()

 class UploadedFile(models.Model):
      url = models.URLField(max_length=1024)
      nonce = models.CharField(max_length=36)

      @classmethod
      def get_unique_nonce(cls):

           while True:
                nonce = str(uuid.uuid4())
                if not cls.objects.filter(nonce=nonce).exists():
                     return nonce



 class Attachment(UploadedFile):
      post = models.ForeignKey(Post)

 # views.py

 class FooPostForm(forms.ModelForm):

      def __init__(self, *args, **kwargs):
           super(PostForm, self).__init__(*args, **kwargs)
           self.initial.setdefault('uuid', UploadedFile.get_unique_uuid())

      def save(self, *args, **kwargs):
           obj = super(FooPostForm, self).save(*args, **kwargs)
           if kwargs.get('commit', True):
                for file in UploadedFile.objects.filter(nonce=obj.nonce)
                     Attachment(uploadedfile_ptr=file, post=obj).save_base(raw=True)
           return obj

      class Meta:
           model = FooPost

 def foo_post(request):
      assert request.method == 'POST'
      form = FooPostForm(request.POST)
      if form.is_valid():
           post = form.save()
      # ...

This works well in my app, but I would like it to also work in the admin interface. How can I inline the attachments in the admin form for the post, even though they are linked indirectly by shared nonce instead of by a foreign key?


Provide a custom modelform for the inline:

 class AttachmentForm(django.forms.ModelForm):

     def save(self, *args, **kwargs):
         obj = super(AttachmentForm, self).save(*args, **kwargs)
         obj.nonce = self.instance.nonce
         if kwargs.get('commit', True):
             obj.save()
         return obj

Exclude the nonce field from the inline:

 class AttachmentInline(admin.TabularInline):

     exclude = ['nonce']
     model = Attachment
     form = AttachmentForm

Come up with a new nonce for a new post:

 class PostAdminForm(django.forms.ModelForm):
     def __init__(self, *args, **kwargs):
         super(PostAdminForm, self).__init__(*args, **kwargs)
         self.initial.setdefault('nonce', S3File.get_unique_nonce())

Use the inline:

 # A particular kind of post
 class FooPostAdmin(admin.ModelAdmin):
     form = PostAdminForm
     inlines = [AttachmentInline]
0

精彩评论

暂无评论...
验证码 换一张
取 消