Tell me how to describe this connection:
There is a table in which there can be different types of records (Type1, Type2 or Type3).
models.py
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
class General(models.Model):
field1 = models.CharField(max_length=512, blank=True, null=True)
field2 = models.CharField(max_length=512, blank=True, null=True)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
class Meta:
db_table = 'General'
class Type1(models.Model):
name = GenericRelation(Product)
address = models.CharField(max_length=512, blank=True, null=True)
number = models.CharField(max_length=256, blank=True, null=True)
class Meta:
db_table = 'Type1'
How to make a connection and choose what I want to type in a type, for example Type2?
This looks correct except the line:
name = GenericRelation(Product)
should be:
name = GenericRelation(General)
in order to form the correct reverse generic relation.
Related
I have a model for my project which is using GenricFroeignKeys for adding Stakeholders to Projects and Reposistories both.
The model is
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
class StakeHolder(models.Model):
"""Model class for Stakeholders of Project and Repos"""
name = models.TextField()
email = models.EmailField()
def __str__(self):
return self.name
class Role(models.Model):
"""This is the model for Role that the stakeholders will have o projects and repos"""
name = models.TextField()
def __str__(self):
return self.name
class ProjectRepoStakeHolder(models.Model):
"""This is a generic models used to define stakeholders on project and repos"""
stake_holder = models.ForeignKey(StakeHolder, on_delete=models.CASCADE)
role = models.ForeignKey(Role, on_delete=models.CASCADE)
limit = models.Q(app_label='pr_reviews', model='repository') | \
models.Q(app_label='pr_reviews', model='project')
# Fields that are mandatory for generic relations
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, limit_choices_to=limit,)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
def __str__(self):
return self.stake_holder.name + "/" + self.role.name + "/" + self.content_object.name
class Project(models.Model):
"""Model class for Project"""
name = models.TextField(unique=True, blank=False, null=False)
uuid = models.UUIDField(unique=True, blank=False, null=False)
is_active = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class Repository(models.Model):
"""Model class for Repository"""
project = models.ForeignKey(Project, on_delete=models.CASCADE, blank=False, null=False)
name = models.TextField(unique=True, blank=False, null=False)
uuid = models.UUIDField(blank=False, null=False)
is_active = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
Now if I have to add a Stakeholder to a Project or a Repository I have to do it by passing object_id (pk of Project or repo)
Like in this Image. I have to pass object id of a repo or project
Is there a way I can add Stakeholders to a Project or Repo by using their names instead, without having to change the pks of project and repo? (Just like how superadmin handles adding FroeigKey relations by a dropdown). Just like this (for ref)
Following is my admin.py file
from django.contrib import admin
from pr_reviews.models import Project, Repository, Role, ProjectRepoStakeHolder, StakeHolder
class ProjectAdmin(admin.ModelAdmin):
list_display = ('id', 'name', 'is_active')
class RepoAdmin(admin.ModelAdmin):
list_display = ('id', 'name', 'is_active', 'project')
class ProjectRepoStakeholderAdmin(admin.ModelAdmin):
list_display = ('stake_holder', 'role', 'content_object', 'content_type')
admin.site.register(Project, ProjectAdmin)
admin.site.register(Repository, RepoAdmin)
admin.site.register(ProjectRepoStakeHolder, ProjectRepoStakeholderAdmin)
admin.site.register(Role)
admin.site.register(StakeHolder)
Please be polite if you want me to improve my question. I don't wanna get bullied like last time when I posted a question here. (just a newbie developer)
I have a project in which some user can perform CRUD activities. I want to record who did what and when. Currently, I am thinking of making a model
class UserAction(models.Model):
user_id = models.CharField(max_length=100)
action_flag = models.CharField(max_length=100)
class_id = models.CharField(max_length=100)
action_taken_at = models.DateTimeField(default=datetime.now())
and making a function that fills my UserAction table. Is there any better way to do this?
app/models.py:
from django.db import models
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey
class Action(models.Model):
sender = models.ForeignKey(User,related_name='user',on_delete=models.CASCADE)
verb = models.CharField(max_length=255)
target_ct = models.ForeignKey(ContentType, blank=True, null=True,
related_name='target_obj', on_delete=models.CASCADE)
target_id = models.PositiveIntegerField(null=True, blank=True)
target = GenericForeignKey('target_ct', 'target_id')
created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-created',)
def __str__(self):
return self.pk
app/admin.py
from .models import Action
admin.site.register(Action)
How you can use it ?
you can now import this models(Action) inside any of yours views.py.
Example if you have a post and a user likes it.you can just write
Action.objects.create(sender=request.user,verb="likes this post",target=post)
and now when you look at your admin you will see that tartget_id=post.pk
Here I assume that a user is authenticated and you can change it for your own.Happy coding!!!
You can do it by creating a model in
Models.py
class Auditable(models.Model):
ip = models.GenericIPAddressField(null=True)
user_agent = models.CharField(max_length=255, blank=True)
remote_host = models.CharField(max_length=255, blank=True)
created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, related_name="%(app_label)s_%(class)s_created_by", null=True, blank=True) # this is for web user
modified_at = models.DateTimeField(auto_now=True, blank=True, null=True)
modified_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, related_name="%(app_label)s_%(class)s_modified_by", null=True, blank=True) # this is for web user
class Meta:
abstract = True
def get_fields(self):
list_fields = ['ip', 'user_agent',
'remote_host', 'created_by', 'modified_by']
return [(field.verbose_name, field._get_val_from_obj(self)) for field in self.__class__._meta.fields if field.name not in list_fields and not
(field.get_internal_type() == "DateTimeField" and
(field.auto_now is True or field.auto_now_add is True)) and
field.concrete and (not field.is_relation or field.one_to_one or
(field.many_to_one and field.related_model))]
You can give any class name (i have given auditable). So all you have to do is pass this class (auditable) in your every model instead of models.Model
For Eg:
class Student(Auditable):
By doing this it will add all the auditable fields records in every table you have created.
Hope you may get your answer by doing this.
Im trying to pull data from external databse with django. I used inspectdb command for get the models, that database have two tables, when I try to get data from the first table, it works...but when I try to get the data from second table throws the next error:
1054, "Unknown column 'hotel_reviews.id' in 'field list'"
The column id dont exist and its correct, but why its looking for it?
This is how i have the models:
from django.db import models
class HotelInfo(models.Model):
country_area = models.CharField(max_length=45)
hotel_id = models.CharField(primary_key=True, max_length=32)
hotel_name = models.TextField(blank=True, null=True)
hotel_url = models.TextField(blank=True, null=True)
hotel_address = models.TextField(blank=True, null=True)
review_score = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)
review_qty = models.IntegerField(blank=True, null=True)
clean = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)
comf = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)
loct = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)
fclt = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)
staff = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)
vfm = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)
wifi = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)
class Meta:
managed = False
db_table = 'hotel_info'
unique_together = (('hotel_id', 'country_area'),)
verbose_name_plural = "hotels"
class HotelReviews(models.Model):
uuid = models.CharField(db_column='UUID', max_length=36, blank=True, null=True) # Field name made lowercase.
hotel_id = models.CharField(max_length=32, blank=True, null=True)
review_title = models.TextField(blank=True, null=True)
review_url = models.TextField(blank=True, null=True)
review_score = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)
review_date = models.DateField(blank=True, null=True)
reviewer_name = models.TextField(blank=True, null=True)
hash_reviewer_name = models.CharField(max_length=200, blank=True, null=True)
reviewer_location = models.CharField(max_length=100, blank=True, null=True)
posting_conts = models.IntegerField(blank=True, null=True)
positive_content = models.TextField(blank=True, null=True)
negative_content = models.TextField(blank=True, null=True)
tag_n1 = models.TextField(blank=True, null=True)
tag_n2 = models.TextField(blank=True, null=True)
tag_n3 = models.TextField(blank=True, null=True)
tag_n4 = models.TextField(blank=True, null=True)
tag_n4 = models.TextField(blank=True, null=True)
tag_n5 = models.TextField(blank=True, null=True)
staydate = models.TextField(blank=True, null=True)
class Meta:
managed = False
db_table = 'hotel_reviews'
verbose_name_plural = "Reviews"
Then I create the serializer like that:
from rest_framework import serializers
from .models import HotelInfo
from .models import HotelReviews
class HotelInfoSerializer(serializers.ModelSerializer):
class Meta:
model = HotelInfo
fields = '__all__'
class HotelReviewSerializer(serializers.ModelSerializer):
class Meta:
model = HotelReviews
fields = '__all__'
This is how I have the views:
from rest_framework import viewsets
from .models import HotelInfo
from .models import HotelReviews
from .serializer import HotelInfoSerializer
from .serializer import HotelReviewSerializer
class HotelInfoViewSet(viewsets.ModelViewSet):
queryset = HotelInfo.objects.filter(review_qty__gte=5)
serializer_class = HotelInfoSerializer
class HotelReviewsViewSet(viewsets.ModelViewSet):
queryset = HotelReviews.objects.all()
serializer_class = HotelReviewSerializer
And this is the urls:
rom rest_framework import viewsets
from .models import HotelInfo
from .models import HotelReviews
from .serializer import HotelInfoSerializer
from .serializer import HotelReviewSerializer
class HotelInfoViewSet(viewsets.ModelViewSet):
queryset = HotelInfo.objects.filter(review_qty__gte=5)
serializer_class = HotelInfoSerializer
class HotelReviewsViewSet(viewsets.ModelViewSet):
queryset = HotelReviews.objects.all()
serializer_class = HotelReviewSerializer
Like I said the first table (hotel_info) works, but the second one (hotel_review) throws the error when I try to get data. Can anybody help me?
If you do not specify a field with primary_key=True, Django will create one implicitly. This field is named id and is an AutoField. Since your HotelReviews model thus does not specifies a primary key field, it will do that for that model.
You should thus assign the uuid as the primary key here:
class HotelReviews(models.Model):
uuid = models.CharField(
primary_key=True,
db_column='UUID',
max_length=36,
blank=True
)
# …
class Meta:
managed = False
db_table = 'hotel_reviews'
verbose_name_plural = 'Reviews'
Note: Django has a UUIDField [Django-doc]
to specify universally unique identifiers. This field also has validators to check if the uuid has the correct
format and is therefore usually better.
Using Django 1.11.6 and Postgres 9.2
If I have the following models:
class RoughDraft(models.Model)
class Manuscript(models.Model):
rough_draft = models.ForeignKey(RoughDraft)
class AudioBook(models.Model):
manuscript = models.ForeignKey(Manuscript)
class Series(models.Model):
class Book(models.Model):
manuscript = models.ForeignKey(Manuscript)
series = models.ForeignKey(Series)
I want to add a Notes model to my project to allow multiple users add comments to RoughDrafts, Manuscripts, Books and AudioBooks. Further, when a RoughDraft becomes a Manuscript or Manuscript becomes a Book or AudioBook, I want the Notes to be carried forward.
Is it better to create a notes model like this:
class Notes(models.Model):
text = models.TextField()
and add a notes = models.ManyToMany(Notes) field to each of RoughDraft, Manuscript, Book, Series and AudioBook
or
class Notes(models.Model):
text = models.TextField()
rough_draft = models.ForeignKey(RoughDraft, null=True, blank=True)
manuscript = models.ForeignKey(Manuscript, null=True, blank=True)
series = models.ForeignKey(Series, null=True, blank=True)
book = models.ForeignKey(Book, null=True, blank=True)
audio_book = models.ForeignKey(AudioBook, null=True, blank=True)
Or should I create a ManuscriptNotes model, a RoughDraftNotes model, etc...
You can use a "generic key" with Django.
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
class Note(models.Model):
content = models.TextField()
author = models.ForeignKey(User, ...)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
This allows you to relate your Note object to any other object in your database
How can I show the columns id, title and the year of the book instead of "Books object"?
This screenshot shows the current state:
My model.py looks like this:
from __future__ import unicode_literals
from django.db import models
class Authors(models.Model):
name = models.CharField(max_length=45, blank=True, null=True)
birthday = models.DateField(blank=True, null=True)
class Meta:
managed = True
db_table = 'authors'
class AuthorsBooks(models.Model):
author_id = models.OneToOneField('Authors', models.DO_NOTHING, db_column='author_id', primary_key=True)
book_id = models.OneToOneField('Books', models.DO_NOTHING, db_column='book_id', primary_key=True)
class Meta:
managed = True
db_table = 'authors_books'
unique_together = (('author_id', 'book_id'),)
class Awards(models.Model):
author = models.OneToOneField('Authors', models.DO_NOTHING, db_column='author', primary_key=True)
award_name = models.CharField(max_length=45)
year = models.IntegerField(blank=True, null=True)
class Meta:
managed = True
db_table = 'awards'
unique_together = (('author', 'award_name'),)
class Books(models.Model):
titel = models.CharField(max_length=45, blank=True, null=True)
year = models.IntegerField(blank=True, null=True)
class Meta:
managed = True
db_table = 'books'
In the class AuthorsBooks I have changed the two foreign keys to OneToOneFields.
My admin.py looks like this:
from django.contrib import admin
from myapp.models import Authors
...
class AwardsInline(admin.TabularInline):
model = Awards
class AuthorsBooksInline(admin.TabularInline):
model = AuthorsBooks
class AuthorsAdmin(admin.ModelAdmin):
list_display = ("name", "birthday" )
inlines = (AwardsInline, AuthorsBooksInline)
admin.site.register(Authors, AuthorsAdmin)
In your models.py file, you can use the special __str__ method in your concerned class to make your objects more descriptive. (This is generally the way most programmers do it)
def __str__(self):
return self.title #if your using 'title' as the attribute to identify your objects
You can choose any other attribute to make your object descriptive.
Good luck!
Add a unicode function in your models.py per model.
class Authors(models.Model):
name = models.CharField(max_length=45, blank=True, null=True)
birthday = models.DateField(blank=True, null=True)
class Meta:
managed = True
db_table = 'authors'
def __unicode__(self):
return self.name
Unicode didnt work for me, but overriding str worked