Django admin site callable field seems not working with python regex - python

I'm adding an additional column repath to the Django.admin site, according to the document, it oughts to work, but once I introduced re package to this function, things went wrong.
here's code sample:
class InfoAddrAdmin(ModelAdmin):
list_display = ('id', 'machineId', 'uptime', 'repath')
list_filter = ('machineId',)
def repath(self, obj):
res = re.search(r"10\.1\d+\.\d+\.\d+", obj.ipaddr)
return res.group()<-Exception comes from here
and the related Model is defined as:
class RemoteAddress(models.Model):
id = models.AutoField(primary_key=True)
machineId = models.CharField(max_length=32)
uptime = models.DateTimeField(default=now)
ipaddr = models.TextField()
A piece of text with lots of IP addresses(i.e. the result of command ipconfig) is stored in the ipaddr field, and that regex searchs for an IP with prefix like '10.1xx.xxx.xxx', which proved working fine.
The main error is:
AttributeError: 'NoneType' object has no attribute 'group'
Using debuging tools, the res is not a None, Just the opposite, it contains the correct value, I'm confused why django believes it is None.
Complete Error stack is avaliable at https://pastebin.com/8WUBdg1F
You may find some information from https://docs.djangoproject.com/en/3.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display

Related

Stop affecting other objects of Django Many to Many model

I'm trying to replicate Blood Group as Model as defined in this picture.
.
In my models.py file I had my code to replicate the blood groups like this
class BloodGroup(models.Model):
name = models.CharField(
max_length=3
)
gives = models.ManyToManyField("self")
receives = models.ManyToManyField("self")
def __str__(self):
return self.name
And in my admin.py file I had registered the model as follows
class BloodGroupAdmin(admin.ModelAdmin):
model = BloodGroup
list_display = ['name', 'get_gives', 'get_receives']
def get_gives(self, obj):
return ", ".join([item.name for item in obj.gives.all()])
def get_receives(self, obj):
return ", ".join([item.name for item in obj.receives.all()])
admin.site.register(BloodGroup, BloodGroupAdmin)
Initially I created plain BloodGroup objects without their gives and receives attribute by providing just their names alone. Thus I create an object for all 8 types. Then as I added relationships to each object I found that adding gives or receives for one object affects other objects gives and receives too, making it impossible to replicate the structure in image.
How do I define relationships, without affecting other objects?
In my admin site, I see field names as "get_gives" and "get_receives". How would i make the admin page show field names as "gives" and "receives" but still displaying objects as strings like the image below?
For first question, probably it is better to have only one relation gives. receives can be found from the reverse query. Like this:
class BloodGroup(models.Model):
name = models.CharField(
max_length=3
)
gives = models.ManyToManyField("self", related_name="receives", symmetrical=False)
Then you only need to add objects to gives. receives will be generated automatically.
For second question, add short_description attribute to function(reference to docs). Like this:
get_gives.short_description = 'Gives'
get_receives.short_description = 'Receives'

Dealing with import of foreignKeys in django-import-export

I don't understand how django-import-export module deals with ForeignKeys.
Here is a simple exemple :
models.py
class TFamilies(models.Model):
id_fam = models.AutoField(primary_key=True, unique=True)
name_fam = models.CharField(max_length=1024, blank=True,verbose_name='Famille')
class TGenus(models.Model):
id_genus = models.AutoField(primary_key=True, unique=True)
name_genus = models.CharField(max_length=1024,verbose_name='nom de genre')
id_fam = models.ForeignKey(TFamilies, null=True, db_column='id_fam', blank=True, verbose_name='Famille')
I would like to allow people adding genus with family associated ! A CSV/XLS with only name_genus and name_fam... (and id left blank).
Family already exist in DB most of the time, Django juste have to find the right id number...
admin.py
class TGenusResource(resources.ModelResource):
name_fam = fields.Field(widget=widgets.ForeignKeyWidget(TFamilies, 'name_fam'))
class Meta:
model = TGenus
import_id_fields = ['id_genus']
class TGenusAdmin(ImportExportActionModelAdmin):
form = TGenusAdminForm
resource_class = TGenusResource
pass
This configuration lead to error in import interface :
Line number: 1 - 'NoneType' object has no attribute 'name_fam'
Traceback (most recent call last):
File "/....../lib/python2.7/site-packages/import_export/resources.py", line 348, in import_data
row_result.object_repr = force_text(instance)
File "......./lib/python2.7/site-packages/django/utils/encoding.py", line 85, in force_text
s = six.text_type(s)
AttributeError: 'NoneType' object has no attribute 'name_fam'
I don't understand...
I also tried answer there : django-import-export resource definition for foreignkey field?
and sort of like there : Foreign Key in django migration using django-import-export
Do I have to use before_import to find myself the match ?
I figured out that you have to find yourself the match ! It's impossible to alterate values in a tablib dataset so you have to take entries make changes and put them back in a new line then erase the old one.
My excel template contains columns id_genus (empty), name_genus and id_fam filled by the name of the family !
For anyone who landed here I post my way :
def before_import(self, dataset, dry_run):
"""
Make standard corrections to the dataset before displaying to user
"""
i = 0
last = dataset.height - 1
# for all lines, search for id of family given and add a new line at the bottom with it then delete the first one
while i <= last:
# Check if the Genus exist in DB
if (TGenus.objects.filter(name_genus=dataset.get_col(2)[0].capitalize())):
id_genus = TGenus.objects.filter(name_genus=dataset.get_col(2)[0].capitalize())[0].id_genus
else :
id_genus = ''
# Check if the family exists in DB
try:
TFamilies.objects.get(name_fam=dataset.get_col(2)[0].capitalize())
except TFamilies.DoesNotExist:
raise Exception("Family not in DB !")
except TFamilies.MultipleObjectsReturned:
pass
# use of "filter" instead of "get" to prevent duplicate values, select the first one in all cases
dataset.rpush((id_genus,
dataset.get_col(1)[0],
TFamilies.objects.filter(name_fam=dataset.get_col(2)[0].capitalize())[0].id_fam))
dataset.lpop()
i = i + 1
My django admin can be used by non sys-admin so, they can and duplicate genus or families that aren't in DB...
If someone have an idea to deal with errors better, I would like to read it !
Also, I would like to keep the name of the family in the preview, not only her id... If you know how, I have posted another question about that : Is-it possible to customize the template of preview in django import-export?
I believe you need to rename according to field name in model TGenus:
id_fam = fields.Field(widget=widgets.ForeignKeyWidget(TFamilies, 'name_fam'))
instead of:
name_fam = fields.Field(widget=widgets.ForeignKeyWidget(TFamilies, 'name_fam'))

AttributeError when using django-datatrans and django-markitup together

I am trying to use django-datatrans to translate a MarkupField (from django-markitup) on a model. Both apps work correctly independently, but when I register datatrans to translate a MarkupField then I can't add objects in the admin anymore.
Relevant code:
from django.db import models
from markitup.fields import MarkupField
from datatrans.utils import register
class Work(models.Model):
title = models.CharField(max_length=500)
content = MarkupField(help_text=MARKDOWN_HELP)
class WorkTranslation(object):
fields = ('title', 'content')
register(Work, WorkTranslation)
When I try to add a new Work-object in the admin I get the following error:
'unicode' object has no attribute 'raw'
The error happens here, in the markitup-module (in the line rendered = render_func(value.raw):
.../lib/python2.7/site-packages/markitup/fields.py in pre_save
def pre_save(self, model_instance, add):
value = super(MarkupField, self).pre_save(model_instance, add)
rendered = render_func(value.raw)
setattr(model_instance, _rendered_field_name(self.attname), rendered)
return value.raw
Local vars when failing:
add: False
model_instance: <Work: This is the title>
value: u'This is the content.'
self: <markitup.fields.MarkupField: content>
I have tried to inspect the variable value when the Work class is not registered for translation. In that case (and then it does work correctly) it is not a unicode string but an instance of markitup.fields.Markup.
I have not been able to figure out why the type changes and I realize this question is pretty specific. But I hope someone has insights anyway..
Had the same issue with django-modeltranslation and django-markitup when testing it:
class ModelTests(TestCase):
def test_my_class(self):
self.assertRaises(IntegrityError, models.MyClass.objects.create)
It works for me with:
class ModelTests(TestCase):
def test_my_class(self):
with self.assertRaises(IntegrityError):
models.MyClass.objects.create(info='', info_de='')
Where my installed languages are en and de. My default language is en. info is my field with markitup and translation. (I'm testing here that a field is required on MyClass, therefore the IntegrityError.)
(Btw. this produces a slightly different error:
class ModelTests(TestCase):
def test_my_class(self):
self.assertRaises(IntegrityError, models.MyClass.objects.create(info=''))
Error:
AttributeError: 'NoneType' object has no attribute 'raw'
)
Maybe this helps someone.

Python Serialization (to JSON) issue

I'm a bit of a newbie in Python, so go easy on me. I'm writing an AJAX handler in Django. Everything's been pretty straight-forward on this until now. I've been banging my head against this bit for the better part of a day. I'd like to return a JSON string that contains a dict that contains a queryset:
#
# models.py
#
class Project(models.Model):
unique_name = models.CharField(max_length=32, unique=True)
title = models.CharField(max_length=255, blank=True)
description = models.TextField('project description', blank=True)
project_date = models.DateField('Project completion date')
published = models.BooleanField()
class ProjectImage(models.Model):
project = models.ForeignKey('Project', related_name='images')
image = models.ImageField(upload_to=get_image_path)
title = models.CharField(max_length=255)
sort_metric = models.IntegerField()
#
# views.py
#
...
projects = Project.Project.objects.filter(published=True)
...
response_dict({
'success' : True,
'maxGroups' : 5, # the result of some analysis on the projects queryset
'projects' : projects
});
# This one works if I remove 'projects' from the dict
# response = json.dumps( response_dict )
# This one works only on projects
# response = serializers.serialize( 'json', response_dict, relations=('images') )
return HttpResponse( response, mimetype='application/javascript' )
I've commented out the two serialization lines, because:
The first one seems to only work with 'simple' dicts and since projects is included in my dict, it fails with [<Project: Project object>] is not JSON serializable
The second one seems to only work with querysets/models and since the 'outer' part of my dict is non-model, it complains that 'str' object has no attribute '_meta'. Note that I am using the wadofstuff serializer with the understanding that it would resolve the OneToMany relationship as defined in my model. But even when I get this working by only serializing projects, I do not have any of my ProjectImages in the output.
QUESTION 1: What is the best way to serialize the whole response_dict? Surely, I'm not the first person to want to do this, right?
QUESTION 2: Why am I unable to get the ManyToOne relationship to work?
Many thanks for your help.
UPDATE: Just found this one: Django JSON Serialization with Mixed Django models and a Dictionary and it looked promising, but I get 'QuerySet' object has no attribute '_meta' =(
You can't serialize a python object like that. There is a section in the django documentation on what to do.
https://docs.djangoproject.com/en/dev/topics/serialization/#id2
Here is the key part to look at:
json_serializer.serialize(queryset, ensure_ascii=False, stream=response)

ForeignKey model has no Manager (i.e., 'Foo' object has no attribute 'foo_set')

I have searched around for an answer to this but can't find one. When using a ForeignKey, I am consistently getting an error telling me that 'Foo object has no attribute 'foo_set'. I am a bit new to Django/Python, so I'm sure there is a simple answer here, but I haven't been able to find it so far. Here's some code (to store varied Boards for use in a game, each of which should have a number of Hexes associated with it):
Models:
class Boards(models.Model):
boardnum = models.IntegerField(unique=True)
boardsize = models.IntegerField(default=11)
hexside = models.IntegerField(default=25)
datecreated = models.DateTimeField(auto_now_add = True)
class Hexes(models.Model):
boardnum = models.ForeignKey(Boards, null = True)
col = models.IntegerField()
row = models.IntegerField()
cost = models.IntegerField(default=1)
Code (this works):
newboard, createb = Boards.objects.get_or_create(boardnum=boardn)
createb returns True.
Code (this immediately follows the above, and does not work):
try:
hx = newboard.boards_set.create(col=c, row=r)
except Exception, err:
print "error:", err
traceback.print_exc()
Both "err" and "traceback.print_exc()" give: AttributeError: 'Boards' object has no attribute 'boards_set'
I get the same error if I first create the Hexes record with a get_or_create and then try a newboard.boards_set.add() on it.
Any ideas? All suggestions appreciated.
The name that Django uses for a reverse foreign key manager is the name of the model that contains the foreign key, not the name of the model that the manager is on.
In your case, it will be:
newboard.hexes_set.create(col=c,row=r)
I find it useful to use the manage.py shell command to import your models and inspect them (with dir, etc) to check out all the available attributes.

Categories

Resources