简体   繁体   中英

How to add extra fields to related model before Saving to database?

I am new to django and i am creating a simple blog application. So i have 2 tables for blog_posts and blog_comments .

Now In the admin side i have a Registered my Post Model so admin users have the ability to add a post. Also when adding a Post I have added the comments model to be staked inline in the add and Edit Post form. So my admin.py is something like this :

admin.py

from django.core import serializers
from django.http import HttpResponse
from django.utils import timezone
from django.contrib import admin
from .models import Post, Comment


# Register your models here.

class CommentsInline(admin.StackedInline):
    model = Comment
    extra = 1
    fields = ['comment_text']


class PostAdmin(admin.ModelAdmin):
    fieldsets = [
        ('Content', {'fields': ('title', 'body', 'is_published')}),
        ('Date Information', {'fields': ('pub_date', )})
    ]

    inlines = [CommentsInline]

    def save_model(self, request, obj, form, change):
        obj.author = request.user
        if not obj.id:
            obj.created_date = timezone.now()
        obj.updated_date = timezone.now()
        super(PostAdmin, self).save_model(request, obj, form, change)

    def save_related(self, request, form, formsets, change):
        # How do i add extra fields that were not there in the form like user_id  and current timestamp ??

        # right now i am trying this 
        post = form.instance
        post.user = request.user
        post.created_date = timezone.now()
        super(PostAdmin, self).save_related(request, form, formsets, change)


admin.site.register(Post, PostAdmin)

In my posts model i have some fields which are not shown in the add and edit form but i add them before saving to database by modifying the save_model method

I want to do the same thing for the comments model which is Stacked Inline so if a user add's a comment the system should automatically get the user_id and current time stamp and insert them to particular columns in comments table.

I am not sure but i think this should be done using the save-related method but don't know how.

My Models.py

from django.db import models
from django.contrib.auth.models import User


# Create your models here.


class Post(models.Model):
    title = models.CharField(max_length=200)
    body = models.TextField('post body')
    author = models.ForeignKey(User)
    pub_date = models.DateTimeField('date published')
    is_published = models.BooleanField(default=0)
    featured_image = models.CharField(max_length=200)
    created_date = models.DateTimeField('date created')
    updated_date = models.DateTimeField('date Updated')

    def __str__(self):
        return self.title


class Comment(models.Model):
    post = models.ForeignKey(Post)
    user = models.ForeignKey(User)
    comment_text = models.CharField(max_length=200)
    created_date = models.DateTimeField('date created')
    is_published = models.BooleanField(default=0)

    def __str__(self):
        return self.comment_text

this is the error callback trace :

Environment:


Request Method: POST
Request URL: http://127.0.0.1:8000/admin/blog/post/add/

Django Version: 1.8.4
Python Version: 2.7.6
Installed Applications:
('django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'polls',
 'blog')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'django.middleware.security.SecurityMiddleware')


Traceback:
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
  132.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py" in wrapper
  616.                 return self.admin_site.admin_view(view)(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in _wrapped_view
  110.                     response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/views/decorators/cache.py" in _wrapped_view_func
  57.         response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/sites.py" in inner
  233.             return view(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py" in add_view
  1516.         return self.changeform_view(request, None, form_url, extra_context)
File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in _wrapper
  34.             return bound_func(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in _wrapped_view
  110.                     response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in bound_func
  30.                 return func.__get__(self, type(self))(*args2, **kwargs2)
File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in inner
  145.                     return func(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py" in changeform_view
  1468.                 self.save_related(request, form, formsets, not add)
File "/home/webwerks/code/mysite/blog/admin.py" in save_related
  76.         super(PostAdmin, self).save_related(request, form, formsets, change)
File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py" in save_related
  1102.             self.save_formset(request, form, formset, change=change)
File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py" in save_formset
  1090.         formset.save()
File "/usr/local/lib/python2.7/dist-packages/django/forms/models.py" in save
  640.         return self.save_existing_objects(commit) + self.save_new_objects(commit)
File "/usr/local/lib/python2.7/dist-packages/django/forms/models.py" in save_new_objects
  771.             self.new_objects.append(self.save_new(form, commit=commit))
File "/usr/local/lib/python2.7/dist-packages/django/forms/models.py" in save_new
  904.             obj.save()
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py" in save
  734.                        force_update=force_update, update_fields=update_fields)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py" in save_base
  762.             updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py" in _save_table
  846.             result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py" in _do_insert
  885.                                using=using, raw=raw)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py" in manager_method
  127.                 return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py" in _insert
  920.         return query.get_compiler(using=using).execute_sql(return_id)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.py" in execute_sql
  974.                 cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py" in execute
  79.             return super(CursorDebugWrapper, self).execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py" in execute
  64.                 return self.cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/utils.py" in __exit__
  97.                 six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py" in execute
  64.                 return self.cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/sqlite3/base.py" in execute
  318.         return Database.Cursor.execute(self, query, params)

Exception Type: IntegrityError at /admin/blog/post/add/
Exception Value: NOT NULL constraint failed: blog_comment.created_date

Thanks @dan-klasson for the Help.

I finally figured Out How to do this :

Firstly in My CommentsInline Class i had to add a method to update the formsets like this :

admin.py

from django.core import serializers
from django.http import HttpResponse
from django.utils import timezone
from django.contrib import admin
from .models import Post, Comment
from .forms import CommentInlineFormset


# Register your models here.

class CommentsInline(admin.StackedInline):
    model = Comment
    extra = 1
    fields = ['comment_text']
    formsets = CommentInlineFormset

    def get_formset(self, request, obj=None, **kwargs):
        formset = super(YourInline, self).get_formset(request, obj, **kwargs)
        formset.request = request
        return formset



class PostAdmin(admin.ModelAdmin):
    fieldsets = [
        ('Content', {'fields': ('title', 'body', 'is_published')}),
        ('Date Information', {'fields': ('pub_date', )})
    ]

    inlines = [CommentsInline]

    def save_model(self, request, obj, form, change):
        obj.author = request.user
        if not obj.id:
            obj.created_date = timezone.now()
        obj.updated_date = timezone.now()
        super(PostAdmin, self).save_model(request, obj, form, change)


admin.site.register(Post, PostAdmin)

and In my forms.py

from django import forms
from django.utils import timezone


class CommentInlineFormset(forms.models.BaseInlineFormSet):
    def save_new(self, form, commit=True):
        obj = super(CommentInlineFormset, self).save_new(form, commit=False)
        # here you can add anything you need from the request
        obj.user = self.request.user
        obj.created_on = timezone.now()

        if commit:
            obj.save()

        return obj

I haven't tried, this but something like this should work:

def save_related(self, request, form, formsets, change):
    post = form.instance
    post.user = request.user
    post.updated_at = timezone.now()
    super(PostAdmin, self).save_related(request, form, formsets, change)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM