Creating multiple objects of Model using one button in Django - python

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.

Related

Edit Form Submit handler for a Model

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.

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.

Does django have a built-in way of limiting the number of objects a one-to-many relationship can have?

I'm working on a project in django and I have the following (abbreviated) user class:
class CustomUser(AbstractBaseUser):
max_files = models.IntegerField(default=5)
And then I have another class,
class File(models.Model):
user = models.ForeignKey('CustomUser', on_delete=models.CASCADE)
Does django have any way to do either of the following:
Limit the number of Files that my CustomUser class has (limit the number of the "many" in the one to many Foreign Key field) to a constant number
The above, but instead of a constant number the use the User.max_files entry
I don't currently have any database constraints, but I'm planning on using MySQL, so if this is database-specific assume I'm using MySQL.
You can override the save() method of your model to check if you have exceeded the max number. Overriding model methods is documented here:
https://docs.djangoproject.com/en/dev/topics/db/models/#overriding-predefined-model-methods
Alternatively If you are using a ModelForm you can implement validation as documented on the Django doc pages:
https://docs.djangoproject.com/en/dev/ref/forms/validation/

django user and custom user class

In Django you have some naturally defined User class. My app also has a User class defined (they dont conflict, that's not the question)
My question is, since these two User classes conceptually represent the same thing (well, users) then it would be natural to integrate them. That is, have a single User class that contains all methods and variables of both classes.
What is the best way to achieve this?
There are (at least) two possibilities:
1) Use the 'custom user' functionality of Django (since Django 1.5), or
2) Use a OneToOneField to the django.contrib.auth User from your own user class.
The first allows you to customize more, but you might get some problems if you try to use third-party-apps that are either not ready for custom users or need specific properties of the stock User. For example, Django Guardian doesn't work if you remove the User-Group relationship.
The second is less intrusive, but doesn't allow you to customize the existing fields of User. Also, you need to manually create the instance of your own user class at registration time.
You should read the documentation about Extending the existing User model.
If you wish to store information related to User, you can use a one-to-one relationship to a model containing the fields for additional information. This one-to-one model is often called a profile model, as it might store non-auth related information about a site user. For example you might create an Employee (note: called MyUser below) model:
from django.contrib.auth.models import User
class MyUser(models.Model):
user = models.OneToOneField(User)
newfield1 = models.CharField(...)
AUTH_USER_MODEL = 'myapp.MyUser'

How do I apply Django model Meta options to models that I did not write?

I want to apply the "ordering" Meta option to the Django model User from django.contrib.auth.models. Normally I would just put the Meta class in the model's definition, but in this case I did not define the model. So where do I put the Meta class to modify the User model?
This is how the Django manual recommends you do it:
You could also use a proxy model to define a different default ordering on a model. The standard User model has no ordering defined on it (intentionally; sorting is expensive and we don't want to do it all the time when we fetch users). You might want to regularly order by the username attribute when you use the proxy. This is easy:
class OrderedUser(User):
class Meta:
ordering = ["username"]
proxy = True
Now normal User queries will be unorderd and OrderedUser queries will be ordered by username.
Note that for this to work you will need to have a trunk checkout of Django as it is fairly new.
If you don't have access to it, you will need to get rid of the proxy part and implement it that way, which can get cumbersome. Check out this article on how to accomplish this.
Paolo's answer is great; I wasn't previously aware of the new proxy support. The only issue with it is that you need to target your code to the OrderedUser model - which is in a sense similar to simply doing a User.objects.filter(....).order_by('username'). In other words, it's less verbose but you need to explicitly write your code to target it. (Of course, as mentioned, you'd also have to be on trunk.)
My sense is that you want all User queries to be ordered, including in third party apps that you don't control. In such a circumstance, monkeypatching the base class is relatively easy and very unlikely to cause any problems. In a central location (such as your settings.py), you could do:
from django.contrib.auth.models import User
User.Meta.ordering = ['username']
UPDATE: Django 1.5 now supports configurable User models.
You can either subclass User:
class OrderedUser(User):
class Meta:
ordering = ['-id', 'username']
Or you could use the ordering in ModelAdmin:
class UserAdmin(admin.ModelAdmin):
ordering = ['-id', 'username']
# unregister user since its already been registered by auth
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
Note: the ModelAdmin method will only change the ordering in the admin, it won't change the ordering of queries.
Contact the author and ask them to make a change.

Categories

Resources