Django admin crashes when adding or editing object - django

I have a django model:
class Foo(models.Model):
user = models.OneToOneField(User, on_delete=models.PROTECT)
def __str__(self):
return self.user.username
With the admin registered as a model admin.
When I try to either edit an existing Foo object (which I first added directly to the DB with SQL) or click 'add' to create a new Foo object, the server crashes. Does this have something to do with the fact that the User table contains about 50,000 objects, and the server is running out of memory when it tries to load the Foo admin, because it OneToOne keys out to User?
Is there a way around this?

You'll probably want to make user a raw_id_fields field, so Django won't attempt to load those 50,000 User objects.
class FooAdmin(...):
# ...
raw_id_fields = ('user',)
If you're using Django 2.0+, you can also use autocomplete_fields instead.

Related

How can I use the current Site as the default in a Django form using the Sites Framework?

I'm using the Sites Framework and want to save the current site as the default site value for one of my models.
Model:
class MyModel(models.Model):
site = models.ForeignKey(
Site,
on_delete=models.CASCADE,
default=Site.objects.get_current()) # THIS IS WHAT I WANT TO DO (DOESN'T WORK)
...other fields...
Is there a way to automatically save the current Site object as the site attribute of MyModel anytime I save a MyModel instance? Or would I need to do this manually by overriding either the form's or the model's save method, (or similar override)?
You can set the default site.
models.py
def get_current_site():
return Site.objects.get_current().id
class MyModel(models.Model):
site = models.ForeignKey(
Site,
on_delete=models.CASCADE,
default=get_current_site)
This will only work if you have created a site in your database and also set the SITE_ID in settings.py

Django Multiple User types in Django 1.9

I want to create a web app in which I will have two different types of users Employee and Employers. They'll have mostly non common fields.How to implement separate registration of both.
Currently I have inherited from the User model.
models.py
class Category(models.Model):
cname=models.CharField(max_length=250)
def __str__(self):
return self.cname
class Workplace(User):
address=models.TextField(max_length=250)
logo=models.ImageField(upload_to=upload_location,null=True,blank=True)
wcategory=models.ForeignKey(Category,on_delete=models.CASCADE)
class Employee(User):
employee_id=models.CharField(max_length=250)
eworkplace=models.ForeignKey(Workplace,on_delete=models.CASCADE)
In django, you can make them both able to authenticate, or register, by setting a OneToOneField to User in your WorkPlace and Employee models. If you have set this user as AUTH_USER_MODEL = <yourapp.User> in settings, you will be able to register with the models that have set this field.

In Django, is there a way to show the admin for a model under a different app?

I've extended the standard User with a Profile model using a one-to-one relationship:
class Profile(models.Model):
user = models.OneToOneField(User, primary_key=True, editable=False)
# Additional user information fields
This is in an app called account_custom. The issue is that in the admin site, I would like this model to show up along with User under "Authentication and Authorization".
I was able to make this show up in the right place in the admin by setting Meta.app_label:
class Profile(models.Model):
class Meta:
app_label = 'auth'
db_table = 'account_custom_profile'
I set Meta.db_table so this uses the existing database table, and everything seems to function properly.
The problem is that Django wants to generate migrations for this, one in account_custom to delete the table and one in auth to create it again. I'm guessing this would either fail or wipe out the data depending on the order the migrations are run, but the deeper problem is that it's trying to create a migration in auth which isn't part of my code base.
Is there a way around this, or is there some better way to control where a ModelAdmin shows up in the admin site?

Creating custom users in Django and customizing the admin

I need to create custom users in my app.
In the example given in the doc
class CustomUser(models.Model):
user = models.OneToOneField(User)
#custom fields
a user must exists before creating a CustomUser.
What I want to do is to create automatically a User when I create a CustomUser.
In the CustomUser admin (only visible by the superuser), I'd like to have only the custom fields and a few fields from the User model, as well as some form to allow the superuser to change the password for existing instance.
Anybody could help?
The first part of your question is easy, you can use a signal:
def create_custom_user(sender, instance, created, **kwargs):
if created:
custom_user, created = CustomUser.objects.get_or_create(user=instance)
post_save.connect(create_custom_user, sender=User)
As for the second part, theres already a change password form in the admin. To filter out the displayed fields you can create a CustomUserAdmin and register it together with the model. It's pretty self explaining in the django docs.
django docs: list_display

Django model manager use_for_related_fields and ModelAdmin relationships

I am having trouble getting my model manager to behave correctly when using the Admin interface. Basically, I have two models:
class Employee(models.Model):
objects = models.EmployeeManager()
username = models.CharField(max_length=45, primary_key=True)
. . .
class Eotm(models.Model): #Employee of the Month
date = models.DateField()
employee = models.ForeignKey(Employee)
. . .
And I have an EmployeeManager class that overrides the get() method, something like this:
class EmployeeManager(models.Manager):
use_for_related_fields = True
def get(self, *arguments, **keywords):
try:
return super(EmployeeManager, self).get(*arguments, **keywords)
except self.model.DoesNotExist:
#If there is no Employee matching query, try an LDAP lookup and create
#a model instance for the result, if there is one.
Basically, the idea is to have Employee objects automatically created from the information in Active Directory if they don't already exist in the database. This works well from my application code, but when I tried to create a Django admin page for the Eotm model, things weren't so nice. I replaced the default widget for ForeignKey fields with a TextInput widget so users could type a username (since username is the primary key). In theory, this should call EmployeeManager.get(username='whatever'), which would either return an Employee just like the default manager or create one and return it if one didn't already exist. The problem is, my manager is not being used.
I can't find anything in the Django documentation about using custom Manager classes and the Admin site, aside from the generic manager documentation. I did find a blog entry that talked about specifying a custom manager for ModelAdmin classes, but that doesn't really help because I don't want to change the model represented by a ModelAdmin class, but one to which it is related.
I may not be understanding what you're trying to do here, but you could use a custom Form for your Eotm model:
#admin.py
from forms import EotmAdminForm
class EotmAdmin(models.ModelAdmin):
form = EotmAdminForm
#forms.py
from django import forms
from models import Eotm, Employee
class EotmAdminForm(forms.ModelForm)
class Meta:
model = Eotm
def clean_employee(self):
username = self.cleaned_data['employee']
return Employee.get(username=username)
That, in theory, should work. I haven't tested it.