I have a User model that has 20 count field:
class User(models.Model):
username = models.CharField(max_length=16)
password = models.CharField(max_length=40) # sha1
real_name = models.CharField(max_length=12, null=True,blank=True)
phone = models.CharField( max_length=11)
email = models.EmailField(blank=True, null=True )
qq = models.CharField(max_length=10, null=True, blank=True)
address = models.CharField(max_length=64, blank=True, null=True)
id_card = models.CharField(blank=True, null=True, max_length=18, validators=[RegexValidator(regex='^.{18}$', message='身份证长度必须为18', code='nomatch')])
id_card_img_front = models.CharField(max_length=256, blank=True, null=True)
id_card_img_back = models.CharField(max_length=256, blank=True, null=True)
nickname = models.CharField(max_length=16, blank=True, null=True)
profile = models.CharField(max_length=256, blank=True, null=True, default=' ')
usertype = models.ForeignKey(to='UserType', default=1, blank=True)
user_c_type = models.CharField(max_length=4, null=True)
fixed_phone = models.CharField(max_length=16, null=True)
fax = models.CharField(max_length=16, null=True)
main_bussiness = models.CharField(max_length=16, null=True)
main_industry = models.CharField(max_length=16, null=True)
company_name = models.CharField(max_length=32, null=True)
company_address = models.CharField(max_length=32, null=True)
province = models.CharField(max_length=32, null=True, default="--省--")
town = models.CharField(max_length=32, null=True, default="--市--") # 省市县
country_level = models.CharField(max_length=32, null=True, default="--县--")
ctime = models.DateTimeField(auto_now_add=True)
uptime = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=1, null=True, default=1)
And in my Django project, I want to use Paginator to realize paging for user list.
Because the count of my user in my database is no more than 10,000 rows.
So, whether I can get all of the user in my database then paginate them?
user_all = models.User.objects.all()
paginator = Paginator(user_all, 10)
try:
user_list_page = paginator.page(page_number)
except PageNotAnInteger:
user_list_page = paginator.page(1)
except EmptyPage:
user_list_page = paginator.page(paginator.num_pages)
And I don't know whether this method(query out all the rows of user data) is inefficiency.
Or, how to weight the balance of query out the users from database? For a positive limit numbers ( over the count I should change paginate method, less than that I can use my page method )?
Or is there a better method to paginate my users?
The generic ListView brings a paginator. You should make sure that your queryset is sorted, otherwise the pages might repeat some of the objects (that is not a Django issue - paging without a sort order is just not practical).
https://docs.djangoproject.com/en/1.11/ref/class-based-views/generic-display/#listview
from django.views.generic.list import ListView
class UserListView(ListView):
template = 'my_user_list_template.html'
model = User # not django.contrib.User but your's
paginate_by = 10
def get_queryset(self):
return super().get_queryset().order_by('realname', 'pk')
The template will contain all context data required to render pagination, and the max 10 objects for the current page.
There are 3rd party modules like pure_pagination that extend the pagination to allow for other GET parameters in the pagination links: https://github.com/jamespacileo/django-pure-pagination
More links:
https://docs.djangoproject.com/en/1.11/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.paginate_by
See also on the same page: paginate_orphans, paginator_class etc.
Related
I am struggling with a weird issue in Django (4.0.7) where multiple instances for the same primary key are shown in Django Admin, as well as when executing queries. I have displayed the primary keys to make clear that they are identical:
The two classes involved are Collection and Card, where every card has a foreign key to a collection.
class Collection(models.Model):
FREQUENCY_CHOICES = [('never', 'Never'), ('less', 'Less'), ('normal', 'Normal'), ('more', 'More')]
title = models.CharField(max_length=200)
author = models.CharField(max_length=200, blank=True, null=True)
user = models.ForeignKey(User, related_name='collections', on_delete=models.CASCADE)
type = models.CharField(max_length=10, choices=(('books', 'Books'), ('tweets', 'Tweets'), ('articles', 'Articles'), ('podcasts', 'Podcasts')))
custom_id = models.CharField(max_length=200, blank=True, null=True) # e.g. raindropref, amazon book id, etc.
url = models.URLField(blank=True, null=True)
tags = TaggableManager(blank=True)
connection = models.ForeignKey(Connection, related_name='collections', null=True, blank=True, on_delete=models.SET_NULL)
frequency = models.CharField(max_length=10, choices=FREQUENCY_CHOICES, default='normal')
class Card(models.Model):
text = models.TextField()
collection = models.ForeignKey(Collection, related_name='cards', on_delete=models.CASCADE, blank=True)
custom_id = models.CharField(max_length=200, null=True, blank=True)
author = models.CharField(max_length=200, null=True, blank=True)
url = models.URLField(blank=True, null=True)
created_at = models.DateTimeField(default=timezone.now)
favorite = models.BooleanField(default=False)
tags = TaggableManager(blank=True)
notes = models.TextField(blank=True, null=True)
location = models.IntegerField(blank=True, null=True)
I cannot fathom where the issue might be. I have already set up the databse from scratch, with no success.
Here is an example database query:
for c in Collection.objects.all():
print(c.pk, c.id)
12 12
12 12
12 12
13 13
I am having 4 models linked with a foreign key,
class CustomUser(AbstractUser):
username = None
email = models.EmailField(('email address'), unique=True)
phone_no = models.CharField(max_length=255, unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
def __str__(self):
return self.email
class personal_profile(models.Model):
custom_user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
picture = models.ImageField(default='profile_image/pro.png', upload_to='profile_image', blank=True)
role = models.CharField(max_length=255, blank=True, null=True)
gender = models.CharField(max_length=255, blank=True, null=True)
date_of_birth = models.DateField(blank=True, null=True)
def __str__(self):
return str(self.pk)
class academia_profile(models.Model):
custom_user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
education_or_certificate = models.CharField(max_length=255, blank=True, null=True)
university = models.CharField(max_length=255, blank=True, null=True)
def __str__(self):
return str(self.pk)
class contact_profile(models.Model):
custom_user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
country = models.CharField(max_length=255, blank=True, null=True)
state = models.CharField(max_length=255, blank=True, null=True)
city = models.CharField(max_length=255, blank=True, null=True)
def __str__(self):
return str(self.pk)
For extracting the data of those four models, I need to extract it by querying 4 times differently and then by passsing for different variables to HTML templates it something a hectic plus would be reducing the performance speed (I am sure!)
My current queries be like
user_base = CustomUser.objects.get(id=user_id)
user_personal = personal_profile.objects.get(custom_user=user_id)
academia = academia_profile.objects.get(custom_user=user_id)
contact = contact_profile.objects.get(custom_user=user_id)
Is it possible to get all of the four queries values in a single variable by hitting a single join query in ORM ?
also, I want to extract just the country from contact_profile and picture from personal_profile in the join query.
Select_related() can able to work here but how? that's what I am not getting.
You are looking for prefetch_related:
Returns a QuerySet that will automatically retrieve, in a single batch, related objects for each of the specified lookups.
user_base = (
CustomUser
.objects
.prefetch_related( #<-- THIS!
"personal_profile_set",
"academia_profile_set",
"contact_profile_set")
.get(id=user_id))
personal_profile = user_base.personal_profile_set.all()[0]
academia_profile = user_base.academia_profile_set.all()[0]
contact_profile = user_base.contact_profile_set.all()[0]
Btw, if you have only one personal_profile, academia_profile, contact_profile per CustomUser, consider changing ForeignKey by OneToOneField and use select_related.
Currently im working on an Ecommerce project in Django where i have a Order model which has Foreign key relation with Product. So all the product details are fetched from product model. Now im facing issue with the same. Whenever I make any change to Product object its getting updated in all the related Order objects too even for orders placed in past.
Is it possible to keep past order's product values unchanged whenever Product object is updated in future? Please help. Below are the codes for your reference.
Product Model
class Product(models.Model):
measurement_choices = (('Liter', 'Liter'), ('Kilogram', 'Kilogram'), ('Cloth', 'Cloth'),
('Shoe', 'Shoe'))
name = models.CharField(max_length=200)
sku = models.CharField(max_length=30, null=True)
stock = models.CharField(max_length=10, null=True)
measurement = models.CharField(choices=measurement_choices, max_length=20, null=True)
description = models.CharField(max_length=10000)
price = models.DecimalField(max_digits=7, decimal_places=2)
discounted_price = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
image = models.ImageField(upload_to='product/images', default='product.png', null=True,
blank=True)
image_one = models.ImageField(upload_to='product/images', null=True, blank=True)
image_two = models.ImageField(upload_to='product/images', null=True, blank=True)
image_three = models.ImageField(upload_to='product/images', null=True, blank=True)
image_four = models.ImageField(upload_to='product/images', null=True, blank=True)
image_five = models.ImageField(upload_to='product/images', null=True, blank=True)
tags = models.ManyToManyField(Tags)
category = models.ForeignKey(Category,on_delete=models.SET_NULL,null=True,blank=True)
sub_category = models.ForeignKey(SubCategory, on_delete=models.SET_NULL,
null=True,related_name='+')
status = models.CharField(max_length=20, choices=(('Active', 'Active'), ('Inactive',
'Inactive')))
brand = models.ForeignKey(Brand,on_delete=models.PROTECT,blank=True, null=True)
offer = models.ForeignKey(Offer, on_delete=models.CASCADE, null=True, blank=True)
color = models.ForeignKey(Color , blank=True, null=True , on_delete=models.PROTECT)
size_type = models.ForeignKey(Size , blank=True, null=True , on_delete=models.PROTECT)
history = HistoricalRecords()
Order Model
class Order(models.Model):
order_status = (('Pending', 'Pending'), ('Under Process', 'Under Process'), ('Dispatched',
'Dispatched'),
('Delivered', 'Delivered'), ('Cancelled', 'Cancelled'), ('Out for delivery',
'Out for delivery'))
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True, blank=True)
shipping_address = models.ForeignKey(ShippingAddress, on_delete=models.DO_NOTHING, null=True,
blank=True)
order_created = models.DateTimeField(auto_now_add=True,null=True)
date_ordered = models.DateTimeField(null=True)
complete = models.BooleanField(default=False)
transaction_id = models.CharField(max_length=100, null=True)
order_number = models.CharField(max_length=20, unique=True, null=True)
status = models.CharField(choices=order_status, default='Pending', max_length=30)
payment_status = models.CharField(choices=(('Received', 'Received'), ('Failed', 'Failed'),
('Pending', 'Pending')),
default='Pending', max_length=30)
ip_address = models.CharField(max_length=30, null=True)
# Payment details captured from payment gateway
payment_order_id = models.CharField(max_length=100, null=True) # razorpay order id
payment_id = models.CharField(max_length=100, null=True) # Razorpay payment id
payment_signature = models.CharField(max_length=100, null=True)# razorpay paymnet signature
payment_method = models.CharField(max_length=100, null=True)
history = HistoricalRecords()
I think there are a few options for you here if I understand your question correctly.
Either you can serialize the actual product details when saving the order. This could be done by using Django serialization and then storing this serialized product on the order with a JSONField. This way you'll keep the state for a product if you want to display or use the data later.
Another way would be to store a new product with a version ID, instead of updating your old products. This could be done by hooking on the pre save, creating a new version and blocking the saving of the old model. This way you'll store and can reuse the model in your templates. https://docs.djangoproject.com/en/3.2/topics/signals/
The last idea would be to use a historical model insert, such as django-simple-history. This would handle changes and updates for you, but you'll have to relate to a given history instance.
I have a Django website and part of it lists data in rows with the primary key in one of the columns. This works great except for when I have separate users. I'm using foreign keys in each model to separate the different user's data. My problem is that the data for each user has to have a number in the column that increments numerically and does not have any spacing, for instance, 1,2,3,5 is bad. If User1 is uploading data and halfway through User2 uploads a row of data then if I use the primary key the numbers will not be in numerical order for each user and will read 1,2,3,5 for User1 and 4 for User2. I tried forloop counter but I need the numbers all the be assigned to the row and not change if one is deleted. Ive been at this for 2 weeks and am having a really hard time describing my problem. I think I need somesort of Custom User Primary Key, a primary key for each user. Any help at this point is greatly appreciated, Thanks!
I finally figured it out after about a week.
models.py:
class Sheet_Building(models.Model):
user = models.ForeignKey(User, default=True, related_name="Building", on_delete=models.PROTECT)
count_building = models.IntegerField(blank=True, null=True)
date = models.DateField(blank=True, null=True, verbose_name='Inspection Date')
time = models.TimeField(blank=True, null=True, verbose_name='Inspection Time')
inspection_type = models.CharField(max_length=16, choices=INSPECTION_TYPE_BI, blank=True, null=True, verbose_name='Inspection Type')
flname = models.CharField(max_length=25, blank=True, null=True, verbose_name='Inspector')
report_date = models.DateField(blank=True, null=True, verbose_name='Report Date')
department = models.CharField(max_length=29, choices=DEPARTMENT_BI, blank=True, null=True, verbose_name='Department')
responsible_name = models.CharField(max_length=25, blank=True, null=True, verbose_name='Responsible Person')
building_address = models.CharField(max_length=52, choices=BUILDING_ADDRESS, blank=True, null=True, verbose_name='Building and Address')
floor = models.CharField(max_length=8, choices=FLOOR_LEVEL_BI, blank=True, null=True, verbose_name='Floor / Level')
room = models.CharField(max_length=35, blank=True, null=True, verbose_name='Area / Room')
location = models.CharField(max_length=10, choices=LOCATION_BI, blank=True, null=True, verbose_name='Location')
priority = models.IntegerField(blank=True, null=True, verbose_name='Priority')
hazard_level = models.CharField(max_length=20, choices=HAZARD_LEVEL_BI, blank=True, null=True, verbose_name='Hazard Level')
concern = models.CharField(max_length=31, choices=CONCERN_BI, blank=True, null=True, verbose_name='Concern')
codes = models.CharField(max_length=51, choices=CODES_BI, blank=True, null=True, verbose_name='Element and Code')
correction = models.TextField(max_length=160, blank=True, null=True, verbose_name='Corrective Action')
image = models.ImageField(blank=True, null=True, verbose_name='Image', upload_to='gallery')
notes = models.TextField(max_length=500, blank=True, null=True, verbose_name="Inspector's note")
class Meta:
ordering = ['-pk']
def __str__(self):
return self.flname or 'None'
def get_absolute_url(self):
return reverse('list_building')
view.py:
def adddata_building(response):
if response.method == 'POST':
form = SheetForm_Building(response.POST, response.FILES)
if form.is_valid():
instance = form.save(commit=False)
instance.user = response.user #User
if Sheet_Building.objects.filter(user=response.user).values_list('count_building'):
instance.count_building = Sheet_Building.objects.filter(user=response.user).aggregate(count_building=Max('count_building'))['count_building'] + 1 #Count
else:
instance.count_building = 1
instance.save()
response.user.Building.add(instance)
return redirect('list_building')
else:
form = SheetForm_Building()
return render(response, 'sheets/add_data/add_data_building.html', {'form': form})
HTML:
{% for post in object_list %}
{{ post.count_building }}
{% enfor %}
I am trying to create cart using django but i am getting this error. while I try to check that the user is authenticated or no i used customer = request.user.customer but it says user has no attribute customer
Here is my views.py
def cart(request):
if request.user.is_authenticated:
customer = request.user.customer
order, created = OrderModel.objects.get_or_create(customer=customer, complete=False)
items = order.orderitem_set.all()
else:
items = []
context = {}
return render(request, 'Home/cart.html', context)
here is my models.py
class CustomerModel(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE, null=True, blank=True, default='')
customer_name = models.CharField(max_length=1000, null=True)
customer_phone = models.CharField(max_length=20, null=True)
def __str__(self):
return self.customer_name
class OrderModel(models.Model):
customer = models.ForeignKey(CustomerModel, on_delete=models.SET_NULL, null=True, blank=True)
order_date = models.DateTimeField(auto_now_add=True)
complete = models.BooleanField(default=False,null=True,blank=True)
transaction_id = models.CharField(max_length=1000, null=True)
def __str__(self):
return str(self.id)
class OrderItem(models.Model):
product = models.ForeignKey(ProductModel, on_delete=models.SET_NULL, null=True, blank=True)
order = models.ForeignKey(OrderModel, on_delete=models.SET_NULL, null=True, blank=True)
quantity = models.IntegerField(default=0, null=True, blank=True)
date_added = models.DateTimeField(auto_now_add=True)
class Address(models.Model):
customer = models.ForeignKey(CustomerModel, on_delete=models.SET_NULL, null=True, blank=True)
order = models.ForeignKey(OrderModel, on_delete=models.SET_NULL, null=True, blank=True)
address = models.CharField(max_length=10000)
city = models.CharField(max_length=1000)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.address
I am stuck here and cant understand what to do.
I think changing the line customer = request.user.customer to customer = request.user.customermodel may solve your problem. If you want to use customer = request.user.customer add related name to your CustomerModel's field:
user = models.OneToOneField(User, on_delete = models.CASCADE, null=True, blank=True, default='', related_name='customer')
Note: Make sure that your user object has a related profile.
For example add an extra condition to your codes like following:
if hasattr(request.user, 'customer'): # If you have related name otherwise use customermodel
customer = request.user.customer
else:
# Return a proper message here
Because if your user object has no related profile this line of code will raise RelatedObjectDoesNotExist error type.
For the user field of the CustomerModel, you must set "related_name" and "related_query_name" to "customer":
user = models.OneToOneField(User, on_delete = models.CASCADE, null=True, blank=True, default='', related_name='customer', related_query_name='customer')
You have to set the "related_name" parameter in your CustomerModel customer field for reverse access
user = models.OneToOneField(User, related_name="user", on_delete = models.CASCADE, null=True, blank=True, default='')
if you don't set the related name django will generate field name + "_set" for the access (user_set in your example)