overide ForeignKey field - django

Using the django docs example below if i have a similar model setup it will look like this.but looking at the Album app it can be used for my other thing the problem for me will be the ForeignKey if i created a new app Photographer and what to add an Album how will i achieve this that albums mean different things for different people or context
class Musician(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
instrument = models.CharField(max_length=100)
class Album(models.Model):
artist = models.ForeignKey(Musician)
name = models.CharField(max_length=100)
release_date = models.DateField()
num_stars = models.IntegerField()
class Photographer(models.Model):
# some stuff here

You can do this using simple model inheritance as follows:
class Musician(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
instrument = models.CharField(max_length=100)
class Photographer(models.Model):
# some stuff here
class Album(models.Model):
name = models.CharField(max_length=100)
release_date = models.DateField()
num_stars = models.IntegerField()
class PhotoAlbum(Album):
artist = models.ForeignKey(Photographer)
class MusicAlbum(Album):
artist = models.ForeignKey(Musician)

One way to relate an object to any other object is to use a generic relationship.
See: https://docs.djangoproject.com/en/1.4/ref/contrib/contenttypes/#generic-relations for an example of how to accomplish this.
Generics are nice because you can avoid concrete inheritance, unless you need it.

Related

Django add a field to a model based on another model

I have a model for a product:
class Product(models.Model):
name = models.CharField(verbose_name=_("Name"), max_length=120)
slug = AutoSlugField(populate_from="name", verbose_name=_("Slug"), always_update=False, unique=True)
I want to have a separate model ProductFields:
class ProductFields(models.Model):
field_name = models.CharField()
field_type = models.CharField()
field_verbose_name = models.CharField()
field_max_length = models.IntegerField()
filed_null = models.CharField()
field_blank = models.BooleanField()
field_default = models.CharField()
...
So the idea is whenever I add new ProductField I want Product model to migrate that added field to its database.
For Example:
ProductFields.objects.create(field_name='description', field_type='CharField', field_verbose_name='Description', field_max_length=255, filed_null=True, filed_blank=True)
This should transform Product modal to:
class Product(models.Model):
name = models.CharField(verbose_name=_("Name"), max_length=120)
slug = AutoSlugField(populate_from="name", verbose_name=_("Slug"), always_update=False, unique=True)
description = models.CharField(verbose_name="Description", max_length= 255, null=True, blank=True)
Please let me know if you have any idea how this can be done?
If you're looking for a way to create a dynamic model you can look into these suggestions.
HStoreField using django-hstore : https://django-hstore.readthedocs.io/en/latest/
JSONField: JSONField is similar to HStoreField, and may perform better with large dictionaries. It also supports types other than strings, such as integers, booleans and nested dictionaries.https://django-pgfields.readthedocs.io/en/latest/fields.html#json-field
Or you can use a NoSQL database (Django MangoDB or another adaptation)

Having trouble linking two fields with one another, then implementing them to another model

I'm working on a project which helps users find jobs.
So one of the models, named Oferta is used for details about a job. Someone who is looking for emplooyes, just completes a form which is based on this model, and people will be looking at it.
Here's this model:
class Oferta(models.Model):
solicitant = models.ForeignKey(User, on_delete=models.CASCADE)
cor = models.CharField(max_length=50)
dataSolicitare = models.DateField(default=date.today)
denumireMeserie = models.CharField(max_length=50)
locuri = models.IntegerField()
agentEconomic = models.CharField(max_length=50)
adresa = models.CharField(max_length=150)
dataExpirare = models.DateField()
experientaSolicitata = models.CharField(max_length=200)
studiiSolicitate = models.CharField(max_length=200)
judet = models.CharField(max_length=20)
localitate = models.CharField(max_length=25)
telefon = models.CharField(max_length=12)
emailContact = models.EmailField(max_length=40)
rezolvata = models.BooleanField(default=False)
def __str__(self):
return self.cor
The COR field is the code asociated to a job. Also, denumireMeserie means job name.
So these should be linked. Let's say, if code 1 means "Cook", these should be link - there will be no other job with a different code, or another job for code 1.
So, in my opinion, these two fields should have a OneToOne relationship between them, if I'm not mistaken.
But these codes and jobs need to be implemented in the database - so they need a model too.
class CORMeserii(models.Model):
CodCOR = models.CharField(max_length=25, primary_key=True, unique=True)
MeserieCor = models.OneToOneField(CodCOR, max_length=50, unique=True, on_delete=models.CASCADE)
And here is how I tried to do it, but obviously it won't work, because onetoonefield needs a model as the first parameter.
So, my questions are:
How can I link these two fields as I told you, and then link Oferta.cor to CORMeserii.CodCOR and Oferta.denumireMeserie to CORMeserii.MeserieCor?
(because each job with its code and name should be implemented in the database, then chosen in each Oferta (which means offer))
As Dirk pointed out on your previous question, you have not understood what relationship fields do in Django.
A ForeignKey or a OneToOneField gives you access to the entire related object. This means you can access any of the fields on that related object.
So your Oferta model does not need a denumireMeserie field; that belongs on the other model, which we might call "Job". Oferta has a link to that model, ie a ForeignKey:
class Oferta(models.Model):
solicitant = models.ForeignKey(User, on_delete=models.CASCADE)
job = models.ForeignKey('Job', on_delete=models.CASCADE)
and Job has the details of the job:
class Job(models.Model):
cor = models.CharField(max_length=50)
denumireMeserie = models.CharField(max_length=50)
Now you can create a Job and an Oferta for that job:
my_job = Job.objects.create(cor=1, denumireMeserie='Cook')
my_oferta = Job.objects.create(job=my_job, ...rest of the fields...)
Now you can access the job name via the relationship:
print(my_oferta.job.denumireMeserie)
which will give you "Cook".

What is the process that you follow to create model in Django?

What is the process that you follow to create model in Django? Thanks.
The most important part of a model – and the only required part of a model – is the list of database fields it defines. Fields are specified by class attributes. Be careful not to choose field names that conflict with the models API like clean, save, or delete.
Models.py
from django.db import models
class Musician(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
instrument = models.CharField(max_length=100)
class Album(models.Model):
artist = models.ForeignKey(Musician, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
release_date = models.DateField()
num_stars = models.IntegerField()
You can start here Documentation
See also Django Girls Models

Django - counting foreign keys in models

I know how I can count things with annotate (in my view) but I would like to do the same in model (so it would be more reusable).
For example (lets take an example from django documentation) I have this model:
class Author(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
class Publisher(models.Model):
name = models.CharField(max_length=300)
class Book(models.Model):
name = models.CharField(max_length=300)
pages = models.IntegerField()
price = models.DecimalField(max_digits=10, decimal_places=2)
rating = models.FloatField()
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
pubdate = models.DateField()
class Store(models.Model):
name = models.CharField(max_length=300)
books = models.ManyToManyField(Book)
and I can use in view this:
from django.db.models import Count
pubs = Publisher.objects.annotate(num_books=Count('book'))
But how I do that in model?
I know this question is pretty basic (probably) but I'm pretty much beginner in django.
Thanks for answers!
You can use custom managers:
Django docs: Managers
class BookManager(models.Manager):
def get_queryset(self):
return super().get_queryset().annotate(num_books=Count('book'))
class Publisher(models.Model):
name = models.CharField(max_length=300)
books = BookManager()
Now you can call it like this:
pubs = Publisher.books.all()
And you will have num_books with your objects.
You can use classmethod for this.
class Publisher(models.Model):
...
#classmethod
def get_book_count(cls):
return cls.objects.annotate(num_books=Count('book'))
You can call this method as
pubs = Publisher.get_book_count()
Edit - Also check out the answer by #Navid2zp which might be a better solution for you.

django admin inline with abstract class and m2m field

This problem almost drives me crazy :(
I was trying to use the StackedInline in admin interface.
The code below is in django documentation.
model.py
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
admin.py
class MembershipInline(admin.StackedInline):
model = Membership
extra = 1
class PersonAdmin(admin.ModelAdmin):
inlines = (MembershipInline,)
class GroupAdmin(admin.ModelAdmin):
inlines = (MembershipInline,)
But if the Group is an abstract base class and PublicGroup is subclass that inherits from Group. Membership is used to relate PublicGroup and Person.
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='%(class)s_Membership')
class Meta:
abstract = True
class PublicGroup(Group):
pass
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
after running the command
python manage.py sql test
I got error "AssertionError: ForeignKey cannot define a relation with abstract class Group".
After searching for solution, I know foreign key cannot point to a abstract class. Some solutions recommended to use generic relation. So I change the code again.
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = generic.GenericRelation('Membership')
class Meta:
abstract = True
class PublicGroup(Group):
pass
class Membership(models.Model):
person = models.ForeignKey(Person)
content_type = models.ForieignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey()
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
This time the command
python manage.py sql test
returns no error. But I got error when I try to add data on admin interface. The error says Membership is not a foreign key of PublicGroup. StackedInline still doesn't work.
Now I really don't know what to do. Does anyone know how to achieve this function.
Thanks for reading!
Is there any good reason why you use this?
class Meta:
abstract = True
If possible, drop it, and then rebuild your database.
It might be interesting for you to read the answers to this stackoverflow question about the difference between abstract models and regular inheritance.
Your model structure is terrible: a M2M relationship will build a relationship table for both Models you try to connect, just like "Through keyword" in M2M field
As I can see, you just want to build a M2M relation between Person and Model based on Group.
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
type = models.CharField(max_lenght=32) # The Type of Group (Public/Private/etc..)
members = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)