Encapsulating the pythonping function in DJango framework - django

I have been building a web app using the Django framework to allow me to ping certain IPs periodically to see if they are online. The setup of the app requires different IPs in different groups. When I have added the python ping function into my model it says that the IPs are not reachable.
Below is my models.py for the project. As you can see I have included the pythonping ping function to try and ping the IPs in question, but it does not seem to work.
from cgitb import text
from ipaddress import ip_address
from django.db import models
from pythonping import ping
#import macaddress
# Create your models here.
class WS_Building_location(models.Model):
Building = models.CharField(max_length=200)
#date_added = models.DateTimeField(auto_now_add =True)
class Meta:
verbose_name_plural = 'Buildings'
def __str__(self):
return self.Building
class WS_address(models.Model):
"""Wyrestorm address"""
building = models.ForeignKey(WS_Building_location, on_delete=models.CASCADE)
ws_ip = models.GenericIPAddressField()
#mac_address = models.macaddress()
date_added = models.DateTimeField(auto_now_add=True)
ipstr = str(ws_ip)
ip_ping = models.TextField(ping('ipstr', verbose = False))
class Meta:
verbose_name_plural = 'addresses'
def __str__(self):
return self.ws_ip
I have read that the pythonping module needs to have root access in order to create the raw packets it uses as a ping and it is not recommended that django be root for security concerns. Any help would be greatly appreciated as I am a novice at this sort of thing but willing to learn!

Related

Django models for astra datastax db

I have developed a website on Django. Initially, I used Django's default Database which is Sqlite3. Now I want to use Astra Datastax DB which is Cassandra. I am not able to convert Django.dB - models into Cassandra.cqlengine - columns function.
I have searched on the Internet and didn't find appropriate documents which could help me.
from django.db import models
from django.contrib.auth import get_user_model
from datetime import datetime
import uuid
User = get_user_model()
class Profile(models.Model):
"""docstring for Profile."""
usr: str = models.ForeignKey(User, on_delete=models.CASCADE)
id_usr: int = models.IntegerField()
Fname:str = models.TextField(blank=True,null=True)
Mname:str = models.TextField(blank=True,null=True)
Lname:str = models.TextField(blank=True,null=True)
Fhone:int = models.IntegerField(blank=True,null=True)
bio: str = models.TextField(blank=True)
img_profile = models.ImageField(
upload_to='ProfileIMG', default="blankprofile.png")
location: str = models.CharField(max_length=250)
def __str__(self):
return self.usr.username
class Post(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, unique=True)
user: str = models.CharField(max_length=100)
image = models.ImageField(upload_to="img_posts")
caption: str = models.TextField(max_length=250)
created_at = models.DateTimeField(default=datetime.now)
Likes: int = models.IntegerField(default=0)
def __str__(self):
return self.user
class LikePost(models.Model):
postid: str = models.CharField(max_length=100)
username: str = models.CharField(max_length=100)
def __str__(self):
return self.username
class Followers(models.Model):
follower: str = models.CharField(max_length=100)
user: str = models.CharField(max_length=100)
def __str__(self):
return self.user
Specially, I want to convert this into Cassandra language.
img_profile = models.ImageField( upload_to='ProfileIMG', default="blankprofile.png")
The documentation you want to consult is here: https://docs.datastax.com/en/developer/python-driver/3.25/api/cassandra/cqlengine/columns/
These are the available columns for DjangoCassandraModel, which is what you would use instead of django.db.models to get a model backed by Cassandra. You can see a basic example of connecting to DataStax Astra with django_cassandra_engine here: https://github.com/DataStax-Examples/django-cassandra-blog
As for the ImageField, I am not sure of the Django internals here, but I believe it stores a path to the file in the database after putting it on disk at the location specified ("img_posts" in your example).
You could do the same for a Cassandra backed model, or use the Blob column type to store the image data itself. There are a number of articles and examples of doing this out there.
To add to the above answer, the django_cassandra_engine package does not offer anything with the same level of automation as the ImageField found in Django's models (i.e. storing the uploaded image on local disk and saving the string path to the database, all from the field definition in the model).
What you would do is to work at a slightly lower abstraction level with an explicit (Django, pure) form. This would allow you to manually handle the file upload as outlined here: https://docs.djangoproject.com/en/4.1/ref/forms/fields/#filefield .
Once you have saved the file and have the string path to it, you can create ann istance of the corresponding Model and manually save it -- all in the appopriate view function.
As a side note, your original (sqlite-backed) code makes use of foreign keys and "on delete cascade" provision for removing related rows from other tables. This cannot be transported as is to a Cassandra storage, since the database, by itself, does not support the concept of relational integrity. You would have to decide how to handle these deletes and act on them explicitly in your code.

Create Multiple Instances From One Model Django

I'm trying to understand how to create multiple instances on creation of a model in django. Eventually I want to create more than one but I'm just trying to get the signal to work at the moment. This is what I have so far that isn't working. I want it to create a duplicate of this model.
from datetime import datetime, timedelta
import django
from django.conf import settings
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
class BudgetTransaction(models.Model):
"""
Individual transaction for Budget
"""
transaction_types = [
('FI', 'Fixed Income'),
('FE', 'Fixed Expenses'),
('EC', 'Extra Cashflow'),
]
frequencies = [
('one', 'one off'),
('wk', 'weekly'),
('fort', 'fortnightly'),
('mon', 'monthly'),
('yr', 'yearly'),
('day', 'specific day'),
]
today = datetime.today().strftime('%Y-%m-%d')
owner = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
help_text="Owner of the item"
)
transaction_type = models.CharField(max_length=40, choices=transaction_types, default=1)
transaction_name = models.CharField(max_length=100, null=False)
transaction_amount = models.IntegerField(null=False)
next_date = models.DateField(null=False, default=today)
frequency = models.CharField(max_length=20, choices=frequencies, default=1)
complete = models.BooleanField(default=False)
def __str__(self):
return self.transaction_name
class Meta:
ordering = ['next_date']
#receiver(post_save, sender=BudgetTransaction)
def create_forecasted(sender, instance, created, **kwargs):
if created:
today = datetime.today()
this_month = today.month
months_left = 12 - this_month
if sender.frequency == "mon":
BudgetTransaction.objects.create(owner=instance.owner)
Thanks,
Mitchell
I suggest to create a file called signals.py in the app next to models.py and place all your signals there as a cleaner structure I mean.
The #receiver decorator listens to the requests made to the server. If you make a viewset for this model with an endpoint to create a BudgetTransaction model. the receiver will work perfectly. But if this is done from django admin, I think the receiver won't work as you mentioned.
I think this may work here instead of #receiver. post_save.connect() as here https://docs.djangoproject.com/en/4.0/ref/signals/
I solved this by using bulk_create rather than just create. I've put an example below to illustrate my change. It was receiving the request correctly with my original post however the code was just not functioning correctly once it was received. I could be wrong and I hope someone corrects this if it is wrong but I was initially getting a recursive error while using create() which I believe is because every time it ran it would resend a signal to create another item.
BudgetTransaction.objects.bulk_create([BudgetTransaction(
owner=instance.owner,
transaction_amount=1000,
transaction_name=instance.transaction_name,
transaction_type=instance.transaction_type,
next_date="2022-08-08",
)])

DJANGO Install application on runtime

I have an application which is made of several apps. The thing is that by default, only 1 app is installed. I called it 'base'. This base app enables the user to manage users, groups (but that isn't the point here) AND should enable users to install other apps on runtime (that is the point).
I created an Application model.
In my UI, I list all the applications with a button install aside of it.
The idea is, when I click on this button, to :
Mark the application as installed
Add it to the App registry on runtime (that's the blocking point)
Apply the migration for this app
So here are some samples of code :
My Application model :
from django.apps import apps
from django.conf import settings
from django.core import management
from django.db import models
class Application(models.Model):
class Meta:
db_table = 'base_application'
name = models.CharField(max_length=255, unique=True)
verbose_name = models.CharField(max_length=255)
version = models.CharField(max_length=255, null=True, blank=True)
summary = models.CharField(max_length=255)
description = models.TextField(null=True, blank=True)
is_installed = models.BooleanField(default=False)
is_uninstallable = models.BooleanField()
My install() method would look like :
I know there are mistakes in it and that is the point of this question. I don't understand how the App Registry actually works.
Note that I must provide the reverse of it too (uninstall)
def install(self):
self.is_installed = True
self.save()
settings.INSTALLED_APPS.append(self.name)
apps.populate(settings.INSTALLED_APPS)
self.migrate()
My migrate() method :
def migrate(self):
management.call_command('makemigrations', self.name, interactive=False)
management.call_command('migrate', self.name, interactive=False)
The usual error I get is No installed app with label ....
Thanks in advance for your help. I can precise if needed.

Django choices with model objects

Yes, this is an assignment, and yes, I've spent some time on it and now I need help.
My task has two models, Server and Client and they are in 1-N relationship. as noted below
# models.py
class Server(models.Model):
name = models.CharField(max_length=255, unique=True, null=False, blank=False)
maximum_clients = models.IntegerField(default=1,null=False, blank=False)
class Client(models.Model):
name = models.CharField(max_length=255, unique=True, null=False, blank=False)
active = models.BooleanField(default=True)
server = models.ForeignKey(Server)
I have created a form with ModelForm which allows me to create a new client on a given server, but the prerequisite of the task is to only offer servers which have free capacity (their maximum_clients is less than actual clients) so this is what I did
#forms.py
from django.db.models import Count
qs = Server.objects.annotate(Count('client'))
server_choices = []
for server in qs:
if server.client__count < server.maximum_clients:
server_choices.append((server,server))
class ClientForm(forms.ModelForm):
name = forms.CharField(label='Client name')
server = forms.ChoiceField(choices=server_choices)
class Meta:
model = Client
fields = ('name','server',)
This approach populates the select with the right servers based on a precondition that I mentioned. However, saving this form produces an error like Cannot assign "u'fifty'": "Client.server" must be a "Server" instance. Fifty is the name of the server with maximum_clients = 50
There is a similar form on admin screens which I also modified to show only available servers and saving there produces the same error.
This is not the right approach. Apart from the error you are seeing, you will also find that your server_choices only update when you restart the webserver, rather than doing so whenever the Server objects themselves change.
You have a foreign key, and need to select from a subset of the related objects. The correct field for that is a ModelChoiceField; this takes a queryset which you can filter in the definition. Since your filter depends on a field in the same model, you need to use an F object.
class ClientForm(forms.ModelForm):
name = forms.CharField(label='Client name')
server = forms.ModelChoiceField(
queryset=Server.objects.annotate(client_count=Count('client')).filter(client_count__lt=F('maximum_clients')
)

Django admin sharing inlines between apps

I have a few apps in my project that I want to be reusable.
First, I have a base content App, which defines how content can be added to a ContentContainer. This allows other models to inherit ContentContainer to get the ability to show content.
Within the content app, I have a Page model that inherits ContentContainer. In another app called events, I have an Event model that also inherites ContentContainer. Basically, my events app depends on my content app (Which is what I want).
This all works great in modeling. I have this in my content app:
class ContentContainer(admin.ModelAdmin):
#No fields, it just gets referred to by ContentItem
class Meta:
ordering = ['modified']
class ContentItem(TimeStampedModel):
name = models.CharField(max_length=1500)
page_order = models.IntegerField()
container = models.ForeignKey(ContentContainer, blank=True)
#make inheritance know the model type
objects = InheritanceManager()
class Meta:
ordering = [ 'page_order', 'modified', 'name']
def __unicode__(self):
return self.name
def render(self):
return self.name
class TextContent(ContentItem):
text = models.CharField(max_length=5000000)
def render(self):
return '<p>%s</p>' % self.text
Then in my Events app I do this:
class Event(AnnouncementBase, Addressable, ContentContainer):
cost = CurrencyField(decimal_places=2, max_digits=10, blank=True, default=0.00)
start_date = models.DateField(default = datetime.now().date())
start_time = models.TimeField(default = datetime.now().time())
end_date = models.DateField(blank=True, default=None, null = True)
end_time = models.TimeField(blank=True, default=None, null = True)
rsvp_deadline = models.DateTimeField(blank=True, default=None, null = True)
class Meta:
ordering = ['start_date', 'start_time', 'title']
So now events can have content to render.
Here's where things get confusing. I have a slew of inlines defined in admin.py in the content app. They work great there. Also, if I copy an paste them into admin.py in the events app they work there too.
However, I don't want to duplicate code. I want to import the inlines from admin.py into events.py In contents admin.py I have this:
class TextContentInline(admin.TabularInline):
model = models.TextContent
extra = 1
class PageAdmin(ContainerAdmin):
model = models.Page
inlines = [LinkContentInline, TextContentInline]
There are a bunch of these inlines. How can I share them between my admin.py models? If I try to import them in the events admin.py I get an error that says "The model Page is already registered". I've tried about 5 different things I could think of an none of them work. I am wondering if there is no way to do this. Oh I'm using Django 1.3 too.
The "already registered" error happens because when a module is imported, Python executes all the statements in the top level - and one of those is the admin.site.register, which is therefore called multiple times.
It's easy to fix this - just catch the exception and ignore it:
try:
admin.site.register(MyModel, MyModelAdmin)
except admin.sites.AlreadyRegistered:
pass
An alternative is to keep your inline classes in a completely separate module file - admin_inlines.py, perhaps - and import them from there into every admin that needs them.