Django | Automatic creation of objects in the model - python

I have two models 'CardsDesk' and 'Card'.
Example:
class CardsDesk(models.Model):
name = models.CharField(max_length=255, verbose_name='Название колоды', blank=True, null=True)
image = models.ImageField(upload_to='media/',verbose_name='Картинка колоды')
class Card(models.Model):
CHOICES = [
('Мечи', (
('Swords_1', 'Туз мечей'),
('Swords_2', 'Двойка мечей'),
('Swords_3', 'Тройка мечей'),
('Swords_4', 'Четверка мечей'),
('Swords_5', 'Пятерка мечей'),
('Swords_6', 'Шестерка мечей'),
('Swords_7', 'Семерка мечей'),
('Swords_8', 'Восьмерка мечей'),
('Swords_9', 'Девятка мечей'),
('Swords_10', 'Десятка мечей'),
('Swords_11', 'Паж мечей'),
('Swords_12', 'Рыцарь мечей'),
('Swords_13', 'Королева мечей'),
('Swords_14', 'Король мечей'),
)
),
............
I need that when I create a Model of type "CardDeck"
Automatically create 78 objects with automatically selected categories.
Any ideas?
I tried the for loop, I tried the def save create(). So far I have absolutely no idea how to implement it.
Edited To make it easier to understand, I use classic cards:
CARDS_TYPE = [
('Diamonds',
('Diamonds_1', 'Diamonds_1'),
('Diamonds_2', 'Diamonds_2'),
),
('Hearts',
('Hearts_1', 'Hearts_1'),
('Hearts_2', 'Hearts_2'),
),
('Clubs',
('Clubs_1', 'Clubs'),
('Clubs_2', 'Clubs'),
),
]

Do it using Django Signals.
Assuming the following models in models.py:
CARD_TYPE_CHOICES = [
('Swords_1', 'Туз мечей'),
('Swords_2', 'Двойка мечей'),
('Swords_3', 'Тройка мечей'),
('Swords_4', 'Четверка мечей'),
('Swords_5', 'Пятерка мечей'),
]
class CardDeck(models.Model):
name = models.CharField(max_length=255, verbose_name='Название колоды', blank=True, null=True)
image = models.ImageField(upload_to='media/',verbose_name='Картинка колоды')
class Card(models.Model):
deck = models.ForeignKey(CardDeck, on_delete=models.CASCADE)
card_type = models.CharField(default="Swords_1", choices=CARD_TYPE_CHOICES, max_length=32)
Create a file signals.py with the following receiver for post_save event of the CardDeck model:
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import CardDeck, Card, CARD_TYPE_CHOICES
#receiver(post_save, sender=CardDeck)
def create_cards_for_deck(sender, instance, created, **kwargs):
if created:
cards = (Card(card_type=card_type[0], deck=instance) for card_type in CARD_TYPE_CHOICES)
Card.objects.bulk_create(cards)
Finally, bind the signals to your apps.py file like:
from django.apps import AppConfig
class AppnameConfig(AppConfig):
name = 'appname'
def ready(self):
import appname.signals
Read more about bulk_create() method.

Related

How i can get list of data by SELECT * LIKE condition in DRF?

How can I make a request for DRF, as if it would be like a request for SELECT by LIKE condition? Now they are displayed to me like this
but I want to output depending on the values in the columns user_id and user_members_id. I have this code
models.py
from django.contrib.postgres.fields import ArrayField
from django.db import models
from django.contrib.auth.models import User
def user_directory_path(instance, filename):
# file will be uploaded to MEDIA_ROOT / user_<id>/<filename>
return 'user_{0}/{1}'.format(instance.company.id, filename)
# Create your models here.
class Company(models.Model):
name = models.CharField(max_length=40, blank=True)
user_id = models.ForeignKey(User, verbose_name='User', on_delete=models.CASCADE) #models.IntegerField(blank=True)
user_members_id = ArrayField(models.IntegerField(), blank=True)
date_created= models.DateTimeField(auto_now=True)
description = models.TextField(blank=True)
# ready = models.CharField(max_length=10, blank=True)
STATUSES = (
(1, 'Public'),
(2, 'Private'),
(3, 'Protected'),
)
status = models.IntegerField(verbose_name='Status', choices=STATUSES)
THEMES = (
(1, 'Finance'),
(2, 'IT'),
(3, 'Develop'),
(4, 'Building'),
)
theme = models.IntegerField(verbose_name='Theme', choices=THEMES)
icon = models.ImageField(upload_to = user_directory_path, blank=True)
def __str__(self):
return self.name
serializers.py
from rest_framework import serializers
from .models import Company
class CompanySerializer(serializers.ModelSerializer):
class Meta:
model = Company
fields = '__all__'
urls.py
from rest_framework import routers
from .api import CompanyViewSet
router = routers.DefaultRouter()
router.register('api/company', CompanyViewSet, 'company')
urlpatterns = router.urls
views.py
from django.shortcuts import render
# Create your views here.
api.py
from .models import Company
from rest_framework import viewsets, permissions
from .serializers import CompanySerializer
class CompanyViewSet(viewsets.ModelViewSet):
queryset = Company.objects.all()
permission_classes = [
permissions.AllowAny
]
serializer_class = CompanySerializer
How get conditinaled result by specify column value. For example by user_id and is have in user_members_id and if possible, to be limited by token
You can use DRF's SearchFilter
from rest_framework.filters import SearchFilter
class CompanyViewSet(viewsets.ModelViewSet):
queryset = Company.objects.all()
permission_classes = [
permissions.AllowAny
]
serializer_class = CompanySerializer
filter_backends = (SearchFilter,)
search_fields = ['username', 'email']
To search in your API, pass your search keyword using search query parameter.
/path/to/end-point/?search=russell

Django MoneyField: Invalid value for MoneyField

I'm having slight of a problem while using MoneyField in Django.
I have 2 models: Work and Price. And Price gets Work id as a Foreign Key.
In Postman I'm trying to post a Work with a Price, but I keep getting an error.
Here is my work_model:
from django.db import models
from django.contrib.auth import get_user_model
User = get_user_model()
class Work(models.Model):
user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
name = models.CharField(max_length=200)
length = models.IntegerField(null=True)
width = models.IntegerField(null=True)
def __str__(self):
return "{}".format(self.name)
And here my price_model
from django.db import models
from .model_work import *
from djmoney.models.fields import MoneyField
class Price(models.Model):
work = models.OneToOneField(Work, on_delete=models.CASCADE, related_name='price')
price = MoneyField(max_digits=19, decimal_places=4, default_currency='USD', null=True)
shipping = models.IntegerField(null=True)
total = models.IntegerField(null=True)
def __str__(self):
return "{}".format(self.price)
When I'm posting a Work in Postman:
{
"user":"2",
"name":"work 20",
"price":
[
{
"price":20,
"price_currency":"USD",
"shipping":12,
"total":32
}
],
"length":"50",
"width":"60"
}
I keep getting this error:
ValidationError at /works/
["Invalid value for MoneyField: [OrderedDict([('price', <Money: 20.0000 USD>), ('shipping', 12), ('total', 32)])]."]
I've looked everywhere but can't manage to understand my error, does anyone have a clue?
Thanks for your responses!
UPDATE 1:
Forgot to put the serializers.
Here is my work_serializer:
from rest_framework import serializers
from ..models.model_work import Work
from .serializers_user import *
from .serializers_price import *
class WorkIndexSerializer(serializers.ModelSerializer):
"""
Serializer listing all Works models from DB
"""
user = UserIndexSerializer()
price_set = PriceDetailsSerializer(many=True)
class Meta:
model = Work
fields = [
'id',
'name',
'price_set',
'length',
'width',
]
class WorkCreateSerializer(serializers.ModelSerializer):
"""
Serializer to create a new Works model in DB
"""
price = PriceCreateSerializer(many=True)
class Meta:
model = Work
fields = [
'user',
'name',
'price',
'length',
'width',
]
def create(self, validated_data):
price = Price.objects.create(**validated_data)
work = Work.objects.create(**validated_data)
return work
class WorkDetailsSerializer(serializers.ModelSerializer):
"""
Serializer showing details of a Work model from DB
"""
user = UserIndexSerializer()
class Meta:
model = Work
fields = fields = [
'user',
'name',
'price_set',
'length',
'width',
]
And my price_serializer:
from rest_framework import serializers
from ..models.model_price import Price
class PriceIndexSerializer(serializers.ModelSerializer):
"""
Serializer showing Price information when called by Work GET serializers.
Not showing 'work' field to avoid loop.
"""
class Meta:
model = Price
fields = [
'price',
'shipping',
'total'
]
depth = 1
class PriceDetailsSerializer(serializers.ModelSerializer):
"""
Serializer showing Price information when called by Work GET serializers.
Not showing 'work' field to avoid loop.
"""
class Meta:
model = Price
fields = [
'price',
'shipping',
'total'
]
depth = 1
class PriceCreateSerializer(serializers.ModelSerializer):
"""
Serializer to create a new Price when new Work model is created in DB
"""
class Meta:
model = Price
fields = [
'price',
'shipping',
'total'
]
def create(self, validated_data):
work = Work.objects.create(**validated_data)
return work

how to add a button/on click action in Django admin page model

I have a model where I have list of servers...
Here is my model:
class Ipaddress(models.Model):
ip_address=models.CharField("Ip address",max_length=20)
device_type= models.ForeignKey("DeviceType", on_delete=models.CASCADE)
slug = models.SlugField(unique=True)
machine_name=models.CharField("Machine Name",max_length=500)
user=models.CharField("User",max_length=200)
department= models.ForeignKey("Department", on_delete=models.CASCADE)
location= models.ForeignKey("Location", on_delete=models.CASCADE)
updated = models.DateField("Date Updated",null=True)
note =models.TextField()
class Meta:
verbose_name = 'IP Management'
def __str__(self):
return self.ip_address[:50]
I want to add ping server action for every model record and store "Yes" if it revived any response. Here is admin page:
from django.contrib import admin
from pages.models import Ipaddress, DeviceGroup, Location,Department,
from django_admin_listfilter_dropdown.filters import DropdownFilter, RelatedDropdownFilter
class DepartmentAdmin(admin.ModelAdmin):
search_fields = ['name']
class LocationAdmin(admin.ModelAdmin):
search_fields = ['description']
list_display =('description',)
class IpaddressAdmin(admin.ModelAdmin):
prepopulated_fields = {'slug': ('ip_address',)}
search_fields = ('ip_address', 'machine_name')
list_display = ('ip_address', 'device_type', 'machine_name', 'user', 'department','location','updated',)
list_display_links =('ip_address', 'device_type', 'machine_name', 'user', 'department','location','updated',)
autocomplete_fields = ['location','department',]
list_filter = (
('user', DropdownFilter),
('department', RelatedDropdownFilter),
('location', RelatedDropdownFilter),
('device_type', RelatedDropdownFilter),
)
I am thinking to add a button to pop up a small dialog box from where user will confirm ping. Need some help how I can do that?

Django Admin list_display product list

I new in django and I trying modifying a project to learn.
I've two classes in a model ('Order' and 'OrderItem'), the class OrderItem stores all items selected in a client order.
models.py
class Order(models.Model):
STATUS_CHOICES = (
(0, 'Waiting Payment'),
(1, 'Completed'),
(2, 'Canceled'),
)
PAYMENT_OPTION_CHOICES = (
('deposit', 'deposit'),
('paypal', 'Paypal'),
)
user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='User')
status = models.IntegerField(
'Situation', choices=STATUS_CHOICES, default=0, blank=True
)
payment_option = models.CharField(
'Payment Options', choices=PAYMENT_OPTION_CHOICES, max_length=20,
default='deposit'
)
created = models.DateTimeField('Created in', auto_now_add=True)
modified = models.DateTimeField('Modified in', auto_now=True)
objects = OrderManager()
class Meta:
verbose_name = 'Order'
ordering = ('-created',)
def __str__(self):
return 'Order #{}'.format(self.pk)
def products(self):
products_ids = self.items.values_list('product')
return Product.objects.filter(pk__in=products_ids)
def total(self):
aggregate_queryset = self.items.aggregate(
total = models.Sum(
models.F('price') * models.F('quantity'),
output_field = models.DecimalField()
)
)
return aggregate_queryset['total']
class OrderItem(models.Model):
order = models.ForeignKey(Order, verbose_name='Order', related_name='items')
product = models.ForeignKey('event.Product', verbose_name='Product')
quantity = models.PositiveIntegerField('Quantity', default=1)
price = models.DecimalField('Price', decimal_places=2, max_digits=8)
class Meta:
verbose_name = 'Order Item'
def __str__(self):
return '{}'.format(self.product)
In the django admin I can show all Orders and when I click to see more I see all products on this order, but my problem is, I can't list this products of class OrderItem in my list_display, how can I do that?
admin.py
class OrderItemInline(admin.StackedInline):
model = OrderItem
fields = ['product']
readonly_fields = ['product',]
extra = 0
max_num = 0
class OrderAdmin(admin.ModelAdmin):
model = Order
inlines = [ OrderItemInline, ]
readonly_fieldsets = (
(None, {
'fields': ('user','status','order','created')
}),
)
readonly_fields = ['user','status','payment_option']
search_fields = ['user__name', 'user__email']
list_filter = ['status', ]
list_display = ['pk','user','status','created','product']
ordering = ('-created',)
admin.site.register(Order, OrderAdmin)
That's an easy task. Inside your OrderAdmin class, remove the product from the display_list list and add a string that will be the name of a method/callable, say list_products. Now, list_display will show the returned value of that function.
For example, define a list_products method inside the OrderAdmin class.
from django.utils.html import mark_safe
class OrderAdmin(admin.ModelAdmin):
list_display = ['pk', 'user', 'status', 'created', 'list_products']
def list_products(self, obj):
# each obj will be an Order obj/instance/row
to_return = '<ul>'
# I'm assuming that there is a name field under the event.Product model. If not change accordingly.
to_return += '\n'.join('<li>{}</li>'.format(pro_name) for prod_name in obj.items.values_list('product__name', flat=True))
to_return += '</ul>'
return mark_safe(to_return)
That's an easy task. Inside your OrderAdmin class, remove the product from the display_list list and add a string that will be the name of a method/callable, say list_products. Now, list_display will show the returned value of that function.
For example, define a list_products method inside the OrderAdmin class:
from django.utils.html import mark_safe
class OrderAdmin(admin.ModelAdmin):
list_display = ['pk', 'user', 'status', 'created', 'list_products']
def list_products(self, obj):
# each obj will be an Order obj/instance/row
to_return = '<ul>'
# I'm assuming that there is a name field under the event.Product model. If not change accordingly.
to_return += '\n'.join('<li>{}</li>'.format(pro_name) for prod_name in obj.items.values_list('product__name', flat=True))
to_return += '</ul>'
return mark_safe(to_return)
I got it, I don't know if it's the rigth one.
I'm create a list first.
def list_products(self, obj):
products = []
for prod_name in obj.items.values_list('product__name', flat=True):
products.append(''.join(prod_name))
to_return = '<br/>'.join(products)
return mark_safe(to_return)

Django Admin Drag and Drop

Looking for some guidance because I'm entering new territory here in terms of my Django experience. I'm writing a reprographics request app so have created a couple of models:
class Job(models.Model):
id = models.AutoField(primary_key=True) # AutoField?
class Resource(models.Model):
id = models.AutoField(primary_key=True) # AutoField?
job = models.ForeignKey(Job)
file = models.FileField(upload_to="repro/")
The admin view includes the resource as inline
class ResourceInline(admin.TabularInline):
model = Resource
extra = 0
class JobAdmin(admin.ModelAdmin):
model = Job
list_display = ['requestedby','account','requestdate','requireddate','noofsides','noofcopies']
list_filter = ['requireddate']
search_fields = ['requestedby','account']
form = JobForm
fieldsets = [
(None, {'fields': ['requestedby','account','requestdate','requireddate','noofsides','noofcopies'] }),
('Requirements', {'fields': ['color','sided','paper','finishing']}),
('Additional Information', {'fields': ['additionalinfo']}),
]
inlines = [ResourceInline]
admin.site.register(Job,JobAdmin)
I'm planning to use dropzone.js and have got myself a change_form.html that I can customise but at this point I'm a bit lost. How can I replace the inline with my dropzone area and get it working?
Thanks for any help or pointers.
Chris
Use adminsortable2 to drag and drop in Django Admin. This is the github link.
So in you case, the code with adminsortable2 is this below.
"models.py":
from django.db import models
class Job(models.Model):
id = models.AutoField(primary_key=True)
my_order = models.PositiveIntegerField(default=0, blank=False, null=False)
class Meta:
ordering = ['my_order']
class Resource(models.Model):
id = models.AutoField(primary_key=True)
job = models.ForeignKey(Job)
file = models.FileField(upload_to="repro/")
my_order = models.PositiveIntegerField(default=0, blank=False, null=False)
class Meta:
ordering = ['my_order']
"admin.js":
from django.contrib import admin
from adminsortable2.admin import SortableAdminMixin, SortableInlineAdminMixin
from .models import Job, Resource
class ResourceInline(SortableInlineAdminMixin, admin.TabularInline):
model = Resource
extra = 0
#admin.register(Job)
class JobAdmin(SortableAdminMixin, admin.ModelAdmin):
list_display = ['requestedby','account','requestdate','requireddate','noofsides','noofcopies']
list_filter = ['requireddate']
search_fields = ['requestedby','account']
form = JobForm
fieldsets = [
(None, {'fields': ['requestedby','account','requestdate','requireddate','noofsides','noofcopies'] }),
('Requirements', {'fields': ['color','sided','paper','finishing']}),
('Additional Information', {'fields': ['additionalinfo']}),
]
inlines = [ResourceInline]
Then, run this command below after writing the code above to save your sorting:
python manage.py reorder <app.model>
So, in your case, I don't know your app name so if your app name is "work" and I know your model names "Job" and "Resource" so run this command below to save your sorting:
python manage.py reorder work.Job work.Resource

Categories

Resources