How to use Admin Model as foreign key in django? - python

I try to develop a relationship as
One admin can add one or many subscription plans.
I try this but not worked
from django.db import models
from django.contrib import admin
class SubscriptionPlansModel(models.Model):
title = models.CharField(max_length=50)
price = models.IntegerField()
duraion = models.IntegerField()
admin = models.ForeignKey(admin,on_delete=models.CASCADE)

you literally making a ForeignKey relation with a module not a db model

Just create "Admin" class in models file. Then, use it as foreign key.
E.g.
class Admin(admin.ModelAdmin):
pass
class SubscriptionPlansModel(models.Model):
title = models.CharField(max_length=50)
price = models.IntegerField()
duraion = models.IntegerField()
admin = models.ForeignKey(admin,on_delete=models.CASCADE)

Related

Including models inside Inline Models in Django

Is it possible to add models inside inline models in Django?
I have 3 models as below
class Platform(models.Model):
platformId = models.IntegerField(primary_key=True)
name = models.CharField(max_length=100)
class Partner(models.Model):
platform = models.ForeignKey(Platform,on_delete=models.CASCADE)
name = models.CharField(max_length=100)
description = models.TextField()
class Inventory(models.Model):
partner = models.ForeignKey(Partner, on_delete=models.CASCADE)
display = models.BooleanField(default=False)
In admin, I added Partner as inline in Platform as below
from django.contrib import admin
from .models import Platform, Partner, Inventory
class PartnerInline(admin.StackedInline):
model = Partner
extra = 1
class InventoryInline(admin.StackedInline):
model = Inventory
extra = 1
class PlatformAdmin(admin.ModelAdmin):
inlines = [
PartnerInline
]
Now what I want is to add the InventoryInline as part of the partner. Is it Possible?
That means when I add a partner I want to add inventory for each partner.
Inline inside and inline. Is this possible?
Or is there any other way to achieve this?
I am new to Django

foreignkey (user) in models

I read the docs and this post... Django - Foreign Key to User model
I followed what it said and I still cannot get it to work. When I try to run the migrations I get this error in the traceback...
django.db.utils.ProgrammingError: column "author_id" cannot be cast automatically to type integer
HINT: You might need to specify "USING author_id::integer".
I just don't know how to go about fixing that error.
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class BlogCategory(models.Model):
'''model for categories'''
title = models.CharField(max_length=30)
description = models.CharField(max_length=100)
class BlogPost(models.Model):
'''a model for a blog post'''
author = models.ForeignKey(User)
date = models.DateField()
title = models.CharField(max_length=100)
post = models.TextField()
Don't use the User model directly.
From the documentation
Instead of referring to User directly, you should reference the user
model using django.contrib.auth.get_user_model()
When you define a foreign key or many-to-many relations to the user model, you should specify the custom model using the AUTH_USER_MODEL setting.
Example:
from django.conf import settings
from django.db import models
class Article(models.Model):
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
If you created a custom User model, you would use setting.AUTH_USER_MODEL, if not you can go ahead an use User model
Referencing Django User model
the column "author_id" doesn't exist, looks like is the same problem from here : Django suffix ForeignKey field with _id , so to avoid this traceback you may use :
author = models.ForeignKey(User, db_column="user")
I do not know the "settings.AUTH_USER_MODEL" approach but a well-known approach and commonly used is the "Auth.User" model. Something like this on your end.
from django.contrib.auth.models import User
class BlogPost(models.Model):
'''a model for a blog post'''
author = models.ForeignKey(User)
date = models.DateField()
title = models.CharField(max_length=100)
post = models.TextField()

Using Custom User DB Structure in Mysql for Django 1.8

I have a question regarding the table structure for User if I am extending its functionalities, using a MySQL database.
Given the models.py file
class LibraryUser(models.Model):
user_id = models.OneToOneField(User)
is_catalogue_subscriber = models.IntegerField(default=1)
is_research_subscriber = models.IntegerField(default=1)
library_membership_number = models.CharField(max_length=64)
I have a table structure for SQL
CREATE TABLE library_user(
user_id int(10) primary key
is_catalogue_subscriber integer(1) DEFAULT 1
is_research_subscriber = integer(1) DEFAULT 1
library_membership_number = varchar(16)
)
So now, when I fire up my server and access the accounts in the admin page, Django is throwing an error:
Exception Type: OperationalError
Exception Value:
(1054, "Unknown column 'library_user.id' in 'where clause'")
Use
user = models.OneToOneField(User, primary_key=True)
i.e. drop the _id in the attribute name.
In case you simply want to define a richer user model (i.e. add more attributes) 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 a LibraryUser model:
from django.contrib.auth.models import User
class LibraryUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
is_catalogue_subscriber = models.IntegerField(default=1)
is_research_subscriber = models.IntegerField(default=1)
library_membership_number = models.CharField(max_length=64)
Assuming an existing LibraryUser Fred Smith who has both a User and LibraryUser model, you can access the related information using Django’s standard related model conventions:
>>> u = User.objects.get(username='fsmith')
>>> freds_department = u.libraryuser.department
Then to add the profile model’s fields to the user page in the admin do
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from my_user_profile_app.models import LibraryUser
# Define an inline admin descriptor for Employee model
# which acts a bit like a singleton
class LibraryUserInline(admin.StackedInline):
model = LibraryUser
can_delete = False
verbose_name_plural = 'libraryuser'
# Define a new User admin
class UserAdmin(UserAdmin):
inlines = (LibraryUserInline, )
# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
All taken from the official docs
What you are missing is that by default django models automatically include an id field that maps to models.AutoField().
You need to specify that your DB table id is user_id instead of id.
https://docs.djangoproject.com/en/1.8/topics/db/models/#automatic-primary-key-fields
You want to make your user_id the primary key. It should work by adding primary_key=True to that field, like:
class LibraryUser(models.Model):
user_id = models.OneToOneField(User, primary_key=True)
is_catalogue_subscriber = models.IntegerField(default=1)
is_research_subscriber = models.IntegerField(default=1)
library_membership_number = models.CharField(max_length=64)

django admin fails using TabularInline

I built a simple django application and now have a really confusing error message. I think it's because of Tabularinline, but I use it properly according to this documentation.
models.py
from django.db import models
class Person(models.Model):
company = models.CharField(max_length=120)
name = models.CharField(max_length=120)
birthday = models.DateField(null=True, blank=True)
def __unicode__(self):
return self.name
class Note(models.Model):
person = models.ForeignKey(Person)
datetime = models.DateTimeField()
text = models.TextField()
admin.py
from addressbook.models import Person, Note
from django.contrib import admin
class NoteInline(admin.TabularInline):
model = Note
class PersonAdmin(admin.ModelAdmin):
model = Person
inlines = [NoteInline, ]
admin.site.register(Note, NoteInline)
admin.site.register(Person, PersonAdmin)
But I always get this error message:
<class 'addressbook.admin.NoteInline'>: (admin.E202) 'addressbook.Note' has no ForeignKey to 'addressbook.Note'.
Which I would understand but why should have Note a reference to itself If I am using it from Person?
I don't think you need to separately register the NoteInline admin template. Just register the PersonAdmin template and that should include your NoteInline

Django reverse foreign key in admin

I have a Django related question about foreign keys in the admin panel. I'm facing the following situation:
class Driver(models.Model):
name = models.CharField(max_length=200)
executable = models.CharField(max_length=200)
class Device(models.Model):
name = models.CharField(max_length=200)
bound_driver = models.ForeignKey(Driver)
class DriverAssignment(models.Model):
device = models.ForeignKey(Device)
driver = models.ForeignKey(Driver)
Every device needs to have a bound driver (which it uses). DriverAssignment should be the table which shows which driver can be used by which device. So one device can have multiple possibilities of drivers which can be bound. Now i would like to have a dropdown on my admin panel showing all possible drivers for a specific device to select the 'bound_driver'.
How can i do this in Django? This is probably an easy thing for an experienced Django guy. I hope someone can give me a hint since i'm kind of new to Django. Thanks a lot!
For Django >1.8
Use the InlineModelAdmin (docs for 2.2) as explained there:
models.py
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
admin.py
from django.contrib import admin
class BookInline(admin.TabularInline):
model = Book
class AuthorAdmin(admin.ModelAdmin):
inlines = [
BookInline,
]
Change your model Structure to This:
class Driver(models.Model):
name = models.CharField(max_length=200)
executable = models.CharField(max_length=200)
class Device(models.Model):
name = models.CharField(max_length=200)
bound_driver = models.ForeignKey(Driver, related_name="bound_to")
available_drivers = models.ManyToManyfield(Driver)
ManyToManyField would do the same work as DriverAssignment Table.
You can add Available drivers in Available drivers field.
But then You would also Want that bound_driver is one of the Available Drivers. This validation you will have to do in forms. For that you have to over-ride Admin forms. See links
Links of Reference:
ManytoMany field: https://docs.djangoproject.com/en/1.6/ref/models/fields/#django.db.models.ManyToManyField
Model Admin (to over-ride admin functionality):
https://docs.djangoproject.com/en/1.6/ref/contrib/admin/#modeladmin-objects
You will have to spend some time reading and implementing if you want ot learn more. :)
OR
If you want to go with the same structure, than you will have to over-ride the form in ModelAdmin see here and Provide you custom form, which will be something like this:
class CustomForm(ModelForm)
bound_driver = forms.ModelChoiceField(queryset = <your custom queryset that returns only available drivers>, ...)
class Meta:
model = Device
https://docs.djangoproject.com/en/1.6/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form
There is a snippet for inverse inlines. If you still need it you may try this:
https://gist.github.com/mzbyszewska/8b6afc312b024832aa85
It has been used by me for OneToOneField in django 1.5 and 1.6. Unfortunately I did not test it for ForeignKeyField, but the one of the previous users claims that it works for ForeignKeyField either.
The best description of the snippet is contained in it. The Person class is your DriverAssignment class and Device correspond to the Address class in the example below:
Example:
from django.db import models
class Address(models.Model):
street = models.CharField(max_length = 255)
zipcode = models.CharField(max_length = 10)
city = models.CharField(max_length = 255)
class Person(models.Model):
name = models.CharField(max_length = 255)
business_addr = models.ForeignKey(Address,
related_name = 'business_addr')
home_addr = models.OneToOneField(Address, related_name = 'home_addr')
other_addr = models.OneToOneField(Address, related_name = 'other_addr')
You use reverseadmin in the following way:
from django.contrib import admin
from django.db import models
from models import Person
from reverseadmin import ReverseModelAdmin
class AddressForm(models.Form):
pass
class PersonAdmin(ReverseModelAdmin):
inline_type = 'tabular'
inline_reverse = ('business_addr', ('home_addr', AddressForm), ('other_addr' (
'form': OtherForm
'exclude': ()
)))
admin.site.register(Person, PersonAdmin)
inline_type can be either "tabular" or "stacked" for tabular and
stacked inlines respectively.

Categories

Resources