update field with number of row in another table django - django

I'm building a web crawler contain links blogs etc of x website ... , I have field called number_of_crawled_Links and I want to make the value of that filed is the number of rows in another model Where Links Stored i want the process to be automatically without making request any idea how to do that

You cannot do that in fields directly, but it's good idea to do that as a method.
class ModelA(models.Model):
some_field = models.TextField()
class ModelB(models.Model):
model_a = models.ForeignKey(ModelA, on_delete=models.CASCADE)
def get_some_field_value(self):
return self.model_a.some_field
Then ModelB can get dynamically the value of ModelA field some_field. You can do it with any type of values.

Related

Create an object that has a ForeignKey with another object

Assume that I have two models:
class Category(models.Model):
title = models.CharField(max_length=255)
class Product(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
title = models.CharField(max_length=255)
What I wanna accomplish is creating a Product object.
Assume I'll receive category_id from the POST request
>>> category = Category.objects.get(id=category_id)
>>> Product.objects.create(category=category, title='Send the category object')
>>> Product.objects.create(category_id=category_id, title='Send only category id')
As you can see, there are two options, the first is to send category instance to create() method and the second is to send category_id, so my question is which approach is better for performance?
I know that I need to check if that category exists in the DB or not but this is not the case that I'm talking about in the question.
If you have the primary key (category_id) there is no need to fetch the category first, you thus can use:
Product.objects.create(category_id=category_id, title='Send only category id')
which will thus only make one query: a query to create the Product, and thus will avoid querying for the category.
The two .create(…)s will make exactly the same query since Django will simply retrieve the .id of the category object, and make the query with that id.
I know that I need to check if that category exists in the DB or not but this is not the case that I'm talking about in the question.
No, if one would make a request with a category_id for which there is no record for the table behind the Category model, it will raise an IntegrityError: the database will normally ensure that ForeignKeys always point to valid items, so the Category.objects.get(id=category_id) is not necessary: if you are only fetching it to fetch the category, you can omit that.

Django Query ManyToMany with Custom Through Table Field Data

I've been trying to figure this one out for a while now but am confused. Every ManyToMany relationship always goes through a third table which isn't that difficult to understand. But in the event that the third table is a custom through table with additional fields how do you grab the custom field for each row?
Here's a sample table I made. How can I get all the movies a User has watched along with the additional watched field and finished field? This example assumes the user is only allowed to see the movie once whether they finish it or not so there will only be 1 record for each movie they saw.
class Movie(models.Model):
title = models.CharField(max_length=191)
class User(models.Model):
username = models.CharField(max_length=191)
watched = models.ManyToMany(Movie, through='watch')
class Watch(models.Model):
user = models.Foreignkey(User, on_delete=models.CASCADE)
movie = models.Foreignkey(Movie, on_delete=models.CASCADE)
watched = models.DateTimeField()
finished = models.BooleanField()
Penny for your thoughts my friends.
You can uses:
from django.db.models import F
my_user.watched.annotate(
watched=F('watch__watched'),
finished=F('watch__finished')
)
This will return a QuerySet of Movies that contain as extra attributes .watched and .finished.
That being said, it might be cleaner to just access the watch_set, and thus iterate over the Watch objects and access the .movie object for details about the movie. You can use .select_related(..) [Django-doc] to fetch the information about the Movies in the same database query:
for watch in my_user.watch_set.select_related('movie'):
print(f'{watch.movie.title}: {watch.watched}, {watch.finished}')

Best and fastest method to add only unique records based on certain fields in Django

I have a model with multiple fields where data is text type for the most part. I want to put a validation that from now on if a new record is being added, it should be unique based on 3 fields. Here one of the fields is a one-to-many field as is in another table.
I can try fetching all the records and start checking them using for-loop. I tried using annotate but it seems to help if the record is already in the table, but I want to do this validation before adding. I need a fast method for this validation.
class Product(models.Model):
brand = models.TextField(default='{}', null=True)
sub_brand = models.CharField(null=True)
.
.
.
class ProductNetWeight(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='product_net_weight')
net_weight = models.CharField(null=True)
First you modify your model to guarantee uniqueness like this:
class Product(models.Model):
brand = models.TextField(default='{}', null=True)
sub_brand = models.CharField(null=True)
.
.
.
class Meta:
unique_together = ['brand', 'sub_brand']
Then when inserting a new product for example un can use get_or_create like this:
product, created = Product.objects.get_or_create(brand='my brand', sub_brand='my sub brand')
If the product already exists, it will be returned in product and created is going to be False, otherwise it will return a new product and created is going to be True

Django forms with odd model relationship

I am working with an existing database that I can not modify and having some trouble trying to deal with presenting forms for modifying the database in Django. The structure in question is as follows and all models are unmanaged.
class Persons(models.Model):
personid = models.BigIntegerField(primary_key=True, db_column='PersonID')
....
class Phones(models.Model):
phoneid = models.BigIntegerField(primary_key=True, db_column='PhoneID')
number = models.CharField(max_length=60, db_column='Number', blank=True)
type = models.CharField(max_length=15, db_column='Type', blank=True)
...
class Personsphones(models.Model):
personphoneid = models.BigIntegerField(primary_key=True, db_column='PersonPhoneID')
personid = models.ForeignKey(Persons, db_column='PersonID')
phoneid = models.ForeignKey(Phones, db_column='PhoneID')
...
I want to create a form to display all of the 'Phones' associated with a particular 'Persons' and in addition be able to modify/add/remove 'Phones' belonging to a 'Persons'. Right now the only thing I can think of is to display the 'Phones' in a modelformset and then if one is added or removed manually set the 'Personsphones' relation. Any ideas on how to best deal with this model setup?
For making changes to your models you may want to use django-south http://south.aeracode.org/docs/
As far as displaying your 'Phone' under your forms.py you may want to set up class meta like so. With this any changes made to models will reflect on change
class Meta:
model = Persons
exclude = ('user')
In models you may want to use Foreignkey fore relationships between phones and Persons. Better seen in action here https://docs.djangoproject.com/en/dev/ref/models/fields/#foreignkey

Django Models Manager for saving custom processed data in a field

A noob here. I have a model class where I want to save something processed in one of the fields of that table. am trying to use a ModelManager for that but do not know if it is possible or how to.
I want to save a custom url for each post here. So I want to have a method in PostManager class which will calculate hash of something (say current time) and save it as a url. I could not find any syntax help so asking it here.
class Post (models.Model):
name = models.CharField(max_length=1000, help_text="required, name of the post")
description = models.TextField(blank=True)
created_datetime = models.DateTimeField(auto_now_add=True, editable=False)
modified_datetime = models.DateTimeField(auto_now=True, editable=False)
custom_hashed_url = models.CharField(unique=True, max_length=1000, editable=False)
def save(self, *args, **kwargs):
#How to refer to the custom_hashed_url in the Post class?
super(Model, self).save()
If you want the url to be saved in the database with the rest of the information, it will need to appear in the model as a field.
Change the url to an appropriate field type and set its 'editable' attribute to False, as you've done with the datetime fields. This will stop it appearing in forms.
You could then override the model's save method (see Django docs) so that it calculates the post's url and adds it automatically as the instance is saved!
Model managers are used for 'model level' interactions that work with many instances, or sets of instances. In this case you are trying to manipulate a single instance. We use a field to store the information in the database for the record and a method (in this case overriding a built-in method to hook into the default behaviours) to calculate the field's value.
Good luck!