Adding Foreign Key to Django Import Export - django

I am trying to import data from a csv using Django_Import Export. I saw other SO posts but they are not helping. Below are the models
Models.py
class TblSubject(amdl.AagamBaseModel):
subject_id = models.AutoField(primary_key=True)
subject_name = models.CharField(max_length=20)
standard = models.ForeignKey('TblStandard', models.DO_NOTHING)
remembrance_credit = models.IntegerField(default=40)
applied_knowledge_credit = models.IntegerField(default=30)
understanding_credit = models.IntegerField(default=30)
subject_credit = models.IntegerField(default=100)
class Meta:
db_table = 'tblsubject'
def __str__(self):
return f'{self.subject_name}'
class SubjectChapter(amdl.AagamBaseModel):
subject_chapter_id = models.AutoField(primary_key=True)
subject = models.ForeignKey('TblSubject', on_delete=models.CASCADE)
chapter_id = models.IntegerField()
chapter_name = models.CharField(max_length=150)
remembrance_credit = models.IntegerField()
applied_knowledge_credit = models.IntegerField()
understanding_credit = models.IntegerField()
chapter_credit = models.IntegerField()
class Meta:
db_table = 'subject_chapter'
def __str__(self):
return f'{self.chapter_id} {self.chapter_name} : {self.subject}'
Here is the admin.py
from django.contrib import admin
from import_export import resources, fields
from import_export.widgets import ForeignKeyWidget
from .models import SubjectChapter, TblSubject
from import_export.admin import ImportExportModelAdmin
class SubjectChapterResource(resources.ModelResource):
class Meta:
model = SubjectChapter
import_id_fields = ('subject_chapter_id',)
subject = fields.Field(
column_name='subject_name',
attribute='subject_name',
widget=ForeignKeyWidget(TblSubject, 'subject_id'))
class SubjectChapterAdmin(ImportExportModelAdmin):
resource_class = SubjectChapterResource
admin.site.register(SubjectChapter, SubjectChapterAdmin)
And i am getting this below error
I am inserting data for SUBJECTCHAPTER from csv where the SUBJECT column is a foreign key from TBLSUBJECT and it contains the name of the TBLSUBJECT.

Change this
class SubjectChapterResource(resources.ModelResource):
class Meta:
model = SubjectChapter
import_id_fields = ('subject_chapter_id',)
subject = fields.Field(
column_name='subject_name',
attribute='subject_name',
widget=ForeignKeyWidget(TblSubject, 'subject_name'))
From subject_id to subject_name

Related

How to update fields on import Django?

I need to update fields on import for ManyToMany bulk editing.
When importing, now I can only add products, because when I try to add already existing fields, I get a message about already existing IDs.
How can I update products using import?
admin.py
class ProductResource(resources.ModelResource):
class Meta:
model = Part
class PartAdmin(ImportExportActionModelAdmin):
resource_class = ProductResource
filter_horizontal = ('analog',)
admin.site.register(Part, PartAdmin)
models.py
class Part(models.Model):
brand = models.CharField('Производитель', max_length=100)
number = models.CharField('Артикул', max_length=100, unique=True)
name = models.CharField('Название', max_length=100)
description = models.TextField('Комментарий', blank=True, max_length=5000)
analog = models.ManyToManyField('self', blank=True, related_name='AnalogParts')
images = models.FileField('Главное изображение', upload_to = 'parts/', blank=True)
images0 = models.FileField('Дополнительное фото', upload_to = 'parts/', blank=True)
images1 = models.FileField('Дополнительное фото', upload_to = 'parts/', blank=True)
images2 = models.FileField('Дополнительное фото', upload_to = 'parts/', blank=True)
def __str__(self):
return str(self.brand + " " + self.number + " " + self.name)
return self.name
from django.contrib import admin
from .models import *
from import_export.admin import ImportExportActionModelAdmin
from import_export import resources
from import_export import fields
from import_export.widgets import ForeignKeyWidget
class ProductResource(resources.ModelResource):
#category = fields.Field(column_name='Артикул', attribute='number')
class Meta:
model = Part
import_id_field = 'number'
import_id_fields = ('number',)
def skip_row(self, instance, original):
original_id_value = getattr(original, self._meta.import_id_field)
instance_id_value = getattr(instance, self._meta.import_id_field)
if original_id_value != instance_id_value:
return True
if not self._meta.skip_unchanged:
return False
for field in self.get_fields():
try:
if list(field.get_value(instance).all()) != list(field.get_value(original).all()):
return False
except AttributeError:
if field.get_value(instance) != field.get_value(original):
return False
return True
admin.site.register(Kits)
class PartAdmin(ImportExportActionModelAdmin):
resource_class = ProductResource
filter_horizontal = ('analog',)
admin.site.register(Part, PartAdmin)
#class PartAdmin(admin.ModelAdmin):
# filter_horizontal = ('analog',)
#admin.site.register(Part, PartAdmin)

django-rest-framework aggregated sum fields

serializers.py
class BuildPlanNewSerializer(serializers.ModelSerializer):
StatusName = serializers.CharField(source='BuildPlanStatusID.StatusName', read_only=True)
# build_plan_list_new = serializers.StringRelatedField(many=True, read_only=True)
total_build_plan_list = serializers.SerializerMethodField()
def get_total_build_plan_list(self, language):
return language.build_plan_list_new.count()
class Meta:
model = BuildPlanNew
fields = ('StatusName', 'total_build_plan_list')
class BuildPlanListNewSerializer(serializers.ModelSerializer):
sku = serializers.CharField(source='ProductID.sku', read_only=True)
class Meta:
model = BuildPlanListNew
fields = "__all__"
models.py
class BuildPlanNew(models.Model):
emp_id = models.ForeignKey(Employee, on_delete=models.CASCADE, null=True, blank=True)
StartDate = models.DateTimeField()
EndDate = models.DateTimeField()
BuildPlanStatusID = models.ForeignKey(GlobalStatus, on_delete=models.CASCADE)
class BuildPlanListNew(models.Model):
BuildPlanID = models.ForeignKey(BuildPlanNew, on_delete=models.CASCADE, null=True, blank=True, related_name="build_plan_list_new")
ProductID = models.ForeignKey(Product, on_delete=models.CASCADE)
TotalPlanQty = models.IntegerField()
TotalBuiltQty = models.IntegerField())
QtyPreset = models.IntegerField(default=None, max_length=256)
Objective = models.IntegerField(default=None, max_length=256)
QtyAssigned = models.IntegerField(default=None, max_length=256)
view.py
class BuildPlanNewView(viewsets.ModelViewSet):
queryset = BuildPlanNew.objects.all()
serializer_class = BuildPlanNewSerializer
class BuildPlanListNewView(viewsets.ModelViewSet):
queryset = BuildPlanListNew.objects.all()
serializer_class = BuildPlanListNewSerializer
Result i am getting:
[{
"StatusName": "1234",
"total_build_plan_list": 0
}]
Result i am expecting:
[{
"StatusName": "1234",
"total_build_plan_list": 0,
"QtyPreset_count":20,
"Objective_count":30
}]
Here i wants to fetch aggregated sum and average from foreign key table.
Need QtyPreset_count sum as QtyPreset_count
Need Objective_count sum as as Objective_count
I have shared my models views and serializers
Please have a look
just add fields to your serializer like you have done so far
from django.db.models import Sum, Avg
class BuildPlanNewSerializer(serializers.ModelSerializer):
StatusName = serializers.CharField(source='BuildPlanStatusID.StatusName', read_only=True)
# build_plan_list_new = serializers.StringRelatedField(many=True, read_only=True)
total_build_plan_list = serializers.SerializerMethodField()
QtyPreset_count = serializers.SerializerMethodField()
Objective_count = serializers.SerializerMethodField()
def get_total_build_plan_list(self, language):
return language.build_plan_list_new.count()
def get_QtyPreset_count(self, language):
return language.build_plan_list_new.aggregate(Sum('QtyPreset'))
# return language.build_plan_list_new.aggregate(Avg('QtyPreset')) if you need it's average
def get_Objective_count(self, language):
return language.build_plan_list_new.aggregate(Sum('Objective'))
class Meta:
model = BuildPlanNew
fields = ('StatusName', 'total_build_plan_list')

how to count total student according to 'course' model in django

I am trying to count the number of the student according to CourseMasterModel.
I did it in MySQL, but I want to in Django.
select cn.course_name,count(st.id) from course_master
cn,semister_master sem,division_master di,student_profile st where
st.division_id = di.id and di.semister_id = sem.id and sem.course_id =
cn.id GROUP BY cn.course_name;
class CourseMasterModel(models.Model):
course_name = models.CharField(max_length=20,unique=True)
total_semister = mod`enter code here`els.SmallIntegerField()
class Meta:
db_table = "course_master"
verbose_name_plural = 'Course (Department)'
verbose_name = "Course"
def __str__(self):
return self.course_name
class SemisterMasterModel(models.Model):
semister = models.SmallIntegerField()
total_div = models.SmallIntegerField()
course = models.ForeignKey(CourseMasterModel,on_delete=models.PROTECT)
class Meta:
db_table = "Semister_master"
verbose_name_plural = 'Semister'
verbose_name = "semister"
def __str__(self):
return "%s - %d" %(self.course.course_name,self.semister)
class DevisionMasterModel(models.Model):
div_name = models.CharField(max_length=2)
semister = models.ForeignKey(SemisterMasterModel,on_delete=models.CASCADE)
class Meta:
db_table = "division_master"
verbose_name_plural = 'Division'
verbose_name = "Division"
def __str__(self):
return "%s - %s - %s"%(self.semister.course.course_name,self.semister.semister,self.div_name)
class StudentProfileModel(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE,related_name="profile")
division = models.ForeignKey('core.DevisionMasterModel',on_delete=models.CASCADE,verbose_name="Course / Semister / Division")
roll_no = models.IntegerField()
enrollment_no = models.IntegerField(unique=True, error_messages={'unique':"This enrollment number has already been registered."})
def __str__(self):
return self.user.username
class Meta:
db_table = "Student_Profile"
You can annotate your CourseMasterModel, like:
from django.db.models import Count
CourseMasterModel.objects.annotate(
nstudents=Count('semistermastermodel__devisionmastermodel__studentprofilemodel')
)
The CourseMasterModels that arise from this QuerySet have an extra attribute .nstudents that contains the number of related StudentProfileModels.
Note: usually the names of Django models have no Model suffix, so CourseMaster instead of CourseMasterModel.
In case you rename the models, the query is:
from django.db.models import Count
CourseMasterModel.objects.annotate(
nstudents=Count('semistermaster__devisionmaster__studentprofile')
)

How to do a relationship using DRF to another table without foreignKey

I can not do relatioships between two tables without relationships.
My models are :
class exampleModel(models.Model):
quantity = models.IntegerField(blank=False, null=True)
comment = models.CharField(max_length=100 , blank=True, null=True)
class Meta:
db_table = "example"
class Logger(models.Model):
id_table = models.IntegerField()
table = models.CharField(max_length=20 , blank=True, null=True)
comment = models.CharField(max_length=100 , blank=True, null=True)
action = models.CharField(max_length=100 , blank=True, null=True)
date_created = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = "logger"
I already have filled logger Model, but , I have not be able made the exampleSerializer.
My serializers are:
class LoggerSerializer(serializers.ModelSerializer):
class Meta:
db_table = u'logger'
model = Logger
fields = '__all__'
class exampleSerializer(serializers.ModelSerializer):
last_log = LoggerSerializer(read_only=True)
class Meta:
db_table = 'example'
model = ExampleModel
fields = ( 'id' , 'last_log' , 'quantity')
in logger saves :
id_table : 'primary key of example',
table : 'example'
comment : 'custom comment',
action : "CRUD"
You can query last logger in view, then pass it to serializer in context.
Then do something like:
class exampleSerializer(serializers.ModelSerializer):
last_log = serializers.SerializerMethodField()
class Meta:
db_table = 'example'
model = ExampleModel
fields = ('id', 'last_log', 'quantity')
def get_last_log(self, obj):
last_log = obj.state(self.context['last_log'])
last_log_serializer = LoggerSerializer(last_log)
return last_log_serializer.data
You pass to context, with something like:
exampleSerializer(queryset, context ={'last_log': last_log_object})
Also You can do the query in exampleSerializer:
class exampleSerializer(serializers.ModelSerializer):
last_log = serializers.SerializerMethodField()
class Meta:
db_table = 'example'
model = ExampleModel
fields = ('id', 'last_log', 'quantity')
def get_last_log(self, obj):
logger_queryset =Logger.objects.filter(table = self.Meta.db_table, id_table = obj.id)
return LoggerSerializer(logger_queryset).data

I18n translation of model form in Django

I have a form that I want to translate:
Models.py:
class Show(models.Model):
discount_tickets = models.IntegerField("Discount Tickets")
regular_tickets = models.IntegerField("Regular Tickets")
afillate_price = models.IntegerField("Afillate Price")
user_price = models.IntegerField("User Price")
start_time = models.CharField("Event Time", max_length=20)
sale_end_time = models.CharField("Sale End Time", max_length=20)
def __unicode__(self):
return unicode(self.discount_tickets)
class ShowForm(ModelForm):
pass
class Meta:
model = Show
How can I translate the field names?
from django.utils.translation import ugettext_lazy as _
class Show(models.Model):
discount_tickets = models.IntegerField(_("Discount Tickets"))
regular_tickets = models.IntegerField(_("Regular Tickets"))
afillate_price = models.IntegerField(_("Afillate Price"))
user_price = models.IntegerField(_("User Price"))
start_time = models.CharField(_("Event Time"), max_length=20)
sale_end_time = models.CharField(_("Sale End Time"), max_length=20)