Edit Form Submit handler for a Model - python

I have a fairly simple django model in a Wagtail CMS; essentially:
from django.db import models
class Thingy(models.Model):
name = models.CharField(max_length=255, blank=False, null=False, unique=True)
# Many other fields.
panels = [
FieldPanel("name"),
# ...
]
I need to perform an action when this model is saved via the Wagtail model edit form (eg /admin/section/thingy/123/edit).
Currently, I have registered a post_save signal, however this has resulted in the method being called when the model is saved programmatically (via an import sync task).
I've had a look in the Django docs, but can't see anything obvious... is there a way to register a signal for the form submission (ideally after the internal submission and save is handled).
(If it's any relevance; I need to trigger a search reindex based on a relation to the model; anything that references instance 123 of thing Things that was saved needs to be reindexed)

If you are using ModelAdmin, you can customize your edit view and put your reindexing code in there.

Related

Is it possible to create new fields using django admin page interface?

Is it possible to create and delete new charfields or textareas through the Django admin page without harcoding them?
For example, I have a simple model, registered in Django admin page
class DocumentList(models.Model):
title = models.CharField(max_length=200)
def __str__(self):
return self.title
Obviously, it has only one charfield on admin page, something like:
DocumentList: [___________]
How can I add another one and delete her later if needed from Django admin page without actually hardcoding another charfield/textarea in models.py, to make it look like:
DocumentList: [___________]
*****************[___________]
Django models are not meant to be dynamically altered. You have to explicitly add the fields on your model, run migrations to have the fields created in your database backend, and reload your server process (./manage.py runserver does this automatically).
If you want to create a model that can hold an arbitrary amount of text strings instead of just one or a fixed amount, you need to use a many-to-many relation to another model.
You can use a custom form in the admin, either by using the form option of the get_form method. This is the documentation example for how you'd pass a custom form:
from django import forms
from django.contrib import admin
from myapp.models import Person
class PersonForm(forms.ModelForm):
class Meta:
model = Person
exclude = ['name']
class PersonAdmin(admin.ModelAdmin):
exclude = ['age']
form = PersonForm
You can add extra fields, as in any form.
I was wondering why you wanted this. Since you said in a comment it is to submit information to an API, you can also use an action, taking input from the user in an intermediate page.
EDIT: As became apparent in comments, the form needs to be dynamic for the user, and not when it is created. Therefore, the solution is using inlines, which once created and linked to the current model, allow the user to add any number of related forms to the current form.

Extending Django's User model

I have been dealing for a while with Django's authentication system and I just cannot understand why I have to go through this process Django doc! :
from django.contrib.auth.models import User
class Employee(models.Model):
user = models.OneToOneField(User)
department = models.CharField(max_length=100)
... rather than simply extending the "User" class like this:
class Employee(User):
....
... and re-using all the code contained within. I have taken a look at articles like: b-list.org! , and I understand that the problem may be related with the automatic Django database management.
Is there a way in which I can automatically extend the User model without having to create an additional table in the database, so that Django modifies the current database table for me?
I tend to obey the fellas of the django
https://docs.djangoproject.com/en/1.5/topics/auth/customizing/#extending-the-existing-user-model
Because only abstract models don't create tables in django and built-in user model is not

Creating multiple objects of Model using one button in Django

I want to solve my problem, I was looking for answer but I can't find any solution.
Let's say I have a Model:
class AccessCode(models.Model):
access_code = models.CharField(max_length=100, verbose_name='Access code',
unique=True, default=key_generator)
def __str__(self):
return self.access_code
def __unicode__(self):
return self.access_code
There is only one field. What I like to do is to create additional button in admin panel and use this button to automatically create 100 AccessCodes in my database.
So there are 2 questions:
How to create custom button in admin panel to perform some action with it?
How to automatically create 100 objects of some model with one step?
The key_generator is my custom function to generate random string as a default value.
You can use bulk_create method introduced in Django 1.4,
AccessCode.objects.bulk_create([AccessCode() for i in range(100)])
However there are some problems with this approach, from django doc
This has a number of caveats though:
- The model’s save() method will not be called, and the pre_save and post_save signals will not be sent.
- It does not work with child models in a multi-table inheritance scenario.
- If the model’s primary key is an AutoField it does not retrieve and set the primary key attribute, as save() does.
To add action to admin page, please check this answer with details how to do it.

get user profile in django

hello i'm new in python and django
I need a view that get current user profile I know I shoud use get_profile from User but I don't know how to use it . i read the django document and It didn't help me.
this is what I found from doc:
from django.contrib.auth.models import User
profile=request.user.get_profile()
Django's documentation says it all, specifically the part Storing additional information about users. First you need to define a model somewhere in your models.py with fields for the additional information of the user:
models.py
from django.contrib.auth.models import User
class UserProfile(models.Model):
# This field is required.
user = models.OneToOneField(User)
# Other fields here
accepted_eula = models.BooleanField()
favorite_animal = models.CharField(max_length=20, default="Dragons.")
Then, you need to indicate that this model (UserProfile) is the user profile by setting AUTH_PROFILE_MODULE inside your settings.py:
settings.py
...
AUTH_PROFILE_MODULE = 'accounts.UserProfile'
...
You need to replace accounts with the name of your app. Finally, you want to create a profile every time a User instance is created by registering a post_save handler, this way every time you create a user Django will create his profile too:
models.py
from django.contrib.auth.models import User
class UserProfile(models.Model):
# This field is required.
user = models.OneToOneField(User)
# Other fields here
accepted_eula = models.BooleanField()
favorite_animal = models.CharField(max_length=20, default="Dragons.")
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
Accessing the Profile
To access the current user's profile in your view, just use the User instance provided by the request, and call get_profile on it:
def your_view(request):
profile = request.user.get_profile()
...
# Your code
Basically django User models will provide access only for the fields ( firstname,lastname,email,password,is_staff,is_active,last_login).
However if we want to add any extra fields to this model, say we need to add a new column named dateofbirth for every user, then we need to add a column named DOB into User model. But this is not possible as we aren't able to edit django User models.
To achieve this either
1.We can have a separate new table with email id & DOB column, such that a column in User model is mapped with a column in the new table. But this will create a new db instance for every db request. Say if u want to find the DOB of a customer,
First we need to fetch the value of mapped id of a customer from the
User table.
WIth the above value, get DOB from the new table.
In the second method,
Instead of using django User model, use your own customize model with all the fields needed. However if any updation related to security or some enhancement made to django User model we can't use it directly. We need to do more code changes at our end( wherever we use our customize models.) This will be a bit pain for a developer to identify the code & make changes.
To overcome the above issues, django introduce django profile which is very simple and more flexible. The advantages are
Updation/enhancement to the User model can be applied without modifying the code much
No need of creating new db instance to fetch the extra values.
Since the field has onetoone mapping deletion of data from one table will delete others also.
More secure, since we use django models ( no sql injection)
How to Use this:
In settings.py create a variable AUTH_PROFILE_MODULE = "appname.profiletable"
In models.py, create a new table with the fields needed and make sure that the id in User model is onetoone mapped with new table.
create a signal which inserts a row into the new table whenever a new entry is added into User model.
The value in the new table can be accessed using User object itself.
Say, we created a new table extrauser which has DOB, emailid. To find the DOB of a customer, use
a=User.objects.get(email='x#x.xom')
a.get_profile().DOB will give the dateofbirth value from extrauser table.
Hope the above details make you clear in understanding django profile. Incase of any help further, let me know. I have used django profile in my project.
Old question but I thought anyone seeing it today may benefit from this:
Django 1.5 adds the ability to - easily - extend the User model. This may be preferable as you now only got one object to deal with rather than two! Seems the more modern way.
https://hurricanelabs.com/blog/django-user-models/
You need to specify which class is your "Profile" by setting AUTH_PROFILE_MODULE = 'accounts.UserProfile' (for example)
https://docs.djangoproject.com/en/1.4/topics/auth/

Auto-populating created_by field with Django admin site

I want to use the Django admin interface for a very simple web application but I can't get around a problem that should not be that hard to resolve ..
Consider the following:
class Contact(models.Model):
name = models.CharField(max_length=250, blank=False)
created_by = models.ForeignKey(User, blank=False)
I can't find a way to auto-populate the created_by field and make the Django admin aware of it. Most of the method I've seen implies overloading the Object's save method and pass it the request user. They all requires to build your custom views and/or forms.
Optimally the form to create new contacts in the admin site should not show the created_by field (which is quite easy) and auto-populate it with the current user (which seems harder than it should).
http://code.djangoproject.com/wiki/CookBookNewformsAdminAndUser
Involves implementing save methods on your ModelAdmin objects.
You need to specify a default for the field, in this case a method call that gets the current user (see the auth documentation to get the current user).
I really wanted a better solution than the ones I found elsewhere, so I wrote some middleware - implementation on the Populate user Id question. My solution requires no changes to any form or view.
I did it by overriding the save_model method in django admin. Since you mentioned that you wanted to use the Django admin interface. So, I think my solution will be the most appropriate one. The solution goes like this:
First register the Contact model in the admin by excluding the 'created_by' field
#admin.register(Contact)
class Notice(admin.ModelAdmin):
list_display = ('name', 'created_by')
exclude = ('created_by', )
Then override the save_model method in the same class Notice
def save_model(self, request, obj, form, change,):
obj.created_by = request.user
super().save_model(request, obj, form, change)

Categories

Resources