I have used django-import-export package. And want to have related database from csv file of format,
roll_no,student_name,subject_1_mark,subject_2_mark,....subject_n_mark
i'm having difficulty of assigning subject mark to their appropriate field on django ORM
example:
#csv file
roll_no, student_name, FOCP, IT, OS, DS, DL
201,john,56,34,65,34,68
Models.py
class Student(models.Model):
""" Store Student Information """
student_name = models.CharField(max_length=255)
roll_no = models.IntegerField()
class Subject(models.Model):
""" Store Subject Information """
subject_name = models.CharField(max_length=150, null=True, blank=True)
sub_code = models.CharField(max_length=255, unique=True, null=True,blank=True)
class Exam(models.Model):
""" Store Exam Information """
exam_type = models.CharField(max_length=150, null=True, blank=True)
exam_date = models.DateField(null=True, blank=True)
class Mark(models.Model):
""" Store Mark Information """
subject_name = models.ForeignKey(Subject, related_name='marks', null=True, blank=True)
exam = models.ForeignKey(Exam, related_name='marks', null=True, blank=True)
mark = models.IntegerField(null=True, blank=True)
settings.py
INSTALLED_APPS = (
...
'import_export',
)
admin.py
from django.contrib import admin
from import_export.admin import ImportExportModelAdmin
from import_export import resources
from .models import Subject
class SubjectResource(resources.ModelResource):
class Meta:
model = Subject
class SubjectAdmin(ImportExportModelAdmin, admin.ModelAdmin):
resource_class = SubjectResource
admin.site.register(Subject, SubjectAdmin)
Use Fields for mapping
Field represent mapping between object field and representation of this field.
I override before_import and did some additional logic on data that solve my problem. I had opened issue on github https://github.com/django-import-export/django-import-export/issues/644#issuecomment-320966810
Related
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.
# settings.py
INSTALLED_APPS = [
# ...
'simple_history',
# ...
]
MIDDLEWARE = [
# ...
'simple_history.middleware.HistoryRequestMiddleware',
# ...
]
Models:
from django.db import models
from apps.companies.models import Company
from simple_history.models import HistoricalRecords
# Create your models here.
class User(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=20)
history = HistoricalRecords()
class Contact(TimeStamp):
name = models.CharField(max_length=100, verbose_name='Person Name')
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
phone_number = models.CharField(max_length=100, verbose_name='Personal Number', null=True, blank=True)
email = models.EmailField(null=True, blank=True, verbose_name='Personal Email')
designation = models.CharField(max_length=100)
history = HistoricalRecords()
def __str__(self):
return self.name
user = User.objects.first()
is there anyway to get all changes any model by the user
Your question seems similar than this issue on the django-simple-history repository : https://github.com/jazzband/django-simple-history/issues/684
You'd have to query each historical model since they're all in
separate tables. You could build a way to automatically detect which
models are historical and get them though.
How do I display a manytomany column as a list of names instead of ids using Django import-export?
Currently my models and resources.py looks like this and returns a csv with a list of ids for the country column:
models.py
class Country(models.Model):
name = models.CharField(max_length=50, null=False,
blank=False, unique=True)
def __str__(self):
return self.name
class Species(models.Model):
name = models.CharField(max_length=50, null=False, blank=False)
country = models.ManyToManyField(Country)
def __str__(self):
return self.name
resources.py
from import_export import resources,fields
from import_export.widgets import ManyToManyWidget
from .models import Species, Country
class SpeciesResource(resources.ModelResource):
country=fields.Field(attribute='country', widget=ManyToManyWidget(Country), column_name='Country')
name = fields.Field(attribute='name', column_name='Name')
class Meta:
model = Species
fields =('name','country')
export_order = fields
Just add field you need in widget:
widget=ManyToManyWidget(Country, field='name')
Currently I have a site, and I want the user to be able to view their liked articles. I want this to be included in the user api view that is already set up. I have tried the tracks = serializers.StringRelatedField(many=True)that is in the drf docs yet this didn't work. I have also tried the following:
from rest_framework import serializers
from articles.models import Article, CustomUser,FavoriteArticles
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ('title', 'content')
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = CustomUser
fields = '__all__'
class FavoriteArticleSerializer(serializers.ModelSerializer):
class Meta:
model = FavoriteArticles
fields = '__all__'
class UserProfileSerializer(serializers.ModelSerializer):
fav_title = FavoriteArticleSerializer(read_only=False)
class Meta:
model = CustomUser
fields = 'username, git, email, fav_article, fav_title, homepage'
and my models:
from django.db import models
# users/models.py
from django.contrib.auth.models import AbstractUser
from django.db.models.signals import post_save
from django.dispatch import receiver
import uuid
class ProgrammingLanguage(models.Model):
programming_language = models.CharField(max_length=120, null=False, primary_key=True, default="React")
def __str__(self):
return self.programming_language
class Article(models.Model):
title = models.CharField(max_length=25, primary_key=True)
content = models.TextField()
usedfor = models.TextField()
url=models.CharField(max_length=200, null=True)
article_programming_language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE, related_name="article_programming_language", default="react")
score = models.IntegerField(max_length=5, null=0)
def __str__(self):
return self.title
class CustomUser(AbstractUser):
username = models.CharField(max_length=50, unique=True, primary_key=True)
git = models.CharField(max_length=200, null=True)
homepage = models.CharField(max_length=250, null=True)
user_programming_language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE, related_name="most_used_programming_language", default="react")
def __str__(self):
return str(self.username)
class FavoriteArticles(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
fav_title = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='fav_title')
reasons_liked = models.CharField(max_length=120, null=True)
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name="user", default="tom" )
def __unicode__(self):
return '%s: %s' % (self.fav_title, self.reasons_liked)
I think you misunderstood what related_name means. It specifies how you would access a model from its reverse relationship. So I'd recommend you remove it from fields in your FavoriteArticles model and use the default Django already provides (in this case favoritearticles_set):
class FavoriteArticles(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
fav_title = models.ForeignKey(Article, on_delete=models.CASCADE)
reasons_liked = models.CharField(max_length=120, null=True)
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, default="tom")
def __unicode__(self):
return '%s: %s' % (self.fav_title, self.reasons_liked)
This way, you can access favorite articles of a user via my_user.favoritearticles_set.all(). Then, you can change your UserSerializer to include a liked_articles field which is populated from the favoritearticles_set reverse relationship to a user's FavoriteArticles using a source attribute:
class UserSerializer(serializers.ModelSerializer):
liked_articles = FavoriteArticleSerializer(source='favoritearticles_set', many=True, read_only=True)
class Meta:
model = CustomUser
# explicitly include other fields as required
fields = ('username', 'git', 'user_programming_language', 'liked_articles')
Note that we've made this a read_only field, so it will only get populated if you perform a GET request.
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