2

I have been trying to create a way that my Django database will store data for 7 consecutive days because I want to use it to plot a weekly graph but the problem now is that Django doesn't have a datetime field that does that.

'''My Code'''

#Model to save seven consecutive days 
class SevenDayData(models.Model):
    
    '''Stores the date of the latest click and stores the value linked to that date in this case our clicks'''
    day1_date= models.DateField(default=None)
    day1_value= models.CharField(max_length=20)
    
    day2_date= models.DateField(default=None)
    day2_value= models.CharField(max_length=20)
    
    day3_date= models.DateField(default=None)
    day3_value= models.CharField(max_length=20)
    
    day4_date= models.DateField(default=None)
    day4_value= models.CharField(max_length=20)
    
    day5_date= models.DateField(default=None)
    day5_value= models.CharField(max_length=20)
    
    day6_date= models.DateField(default=None)
    day6_value= models.CharField(max_length=20)
    
    day7_date= models.DateField(default=None)
    day7_value= models.CharField(max_length=20)
    
    #updating the model each time the row is saved
    updated_at= models.DateTimeField(auto_now= True)
    
    #function that handles all the saving and switching of the 7 days
    def shift_days(self, new_value):
        
        #getting todays date
        today= date.today()
        
        #shifting every data out from day_7 each time a date is added i.e the 7th day is deleted from the db once the time is due
        self.day7_date, self.day7_value = self.day6_date, self.day6_value #Overwriting each date with the next one
        self.day6_date, self.day6_value = self.day5_date, self.day5_value
        self.day5_date, self.day5_value = self.day4_date, self.day4_value
        self.day4_date, self.day4_value = self.day3_date, self.day3_value
        self.day3_date, self.day3_value = self.day2_date, self.day2_value
        self.day2_date, self.day2_value = self.day1_date, self.day1_value
        
        #writing todays date into the day 1 which actually causes the shifting each time this db is accessed 
        self.day1_date, self.day1_value = today, new_value
        self.save()




'''Error'''


IntegrityError at /go/026099
null value in column "day2_date" of relation "url_shortner_sevendaydata" violates not-null constraint
DETAIL:  Failing row contains (1, 2025-09-13, 11, null, , null, , null, , null, , null, , null, , 2025-09-13 15:16:30.262801+00).
Request Method: GET
Request URL:    http://localhost:8000/go/026099
Django Version: 5.2.1
Exception Type: IntegrityError
Exception Value:    
null value in column "day2_date" of relation "url_shortner_sevendaydata" violates not-null constraint
DETAIL:  Failing row contains (1, 2025-09-13, 11, null, , null, , null, , null, , null, , null, , 2025-09-13 15:16:30.262801+00).
Exception Location: C:\Users\VICT6OR\Desktop\Coding_backup\self_made.project\mini_url_app\env\Lib\site-packages\django\db\backends\utils.py, line 105, in _execute
Raised during:  url_shortner.views.go_to_link
Python Executable:  C:\Users\VICT6OR\Desktop\Coding_backup\self_made.project\mini_url_app\env\Scripts\python.exe
Python Version: 3.12.11
Python Path:    
['C:\\Users\\VICT6OR\\Desktop\\Coding_backup\\self_made.project\\mini_url_app',
 'C:\\Users\\VICT6OR\\miniforge3\\python312.zip',
 'C:\\Users\\VICT6OR\\miniforge3\\DLLs',
 'C:\\Users\\VICT6OR\\miniforge3\\Lib',
 'C:\\Users\\VICT6OR\\miniforge3',
 'C:\\Users\\VICT6OR\\Desktop\\Coding_backup\\self_made.project\\mini_url_app\\env',
 'C:\\Users\\VICT6OR\\Desktop\\Coding_backup\\self_made.project\\mini_url_app\\env\\Lib\\site-packages']
Server time:    Sat, 13 Sep 2025 15:16:30 +0000




'''The view giving me the error '''


def go_to_link(request, pk):
    '''Date clicked'''
    today = datetime.date.today()

    '''Clients IP address'''
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')

    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]  # first IP = client
    else:
        ip = request.META.get('REMOTE_ADDR')

    # Find the URLModel object
    url_details = URLModel.objects.get(uuid=pk)

    # Increment total clicks
    url_to_edit = URLModel.objects.filter(uuid=pk).first()
    url_to_edit.number_of_times_clicked += 1
    url_to_edit.save()

    # Save new click entry
    new_data = Click(url_relation=url_details, time_clicked=today, ip_address=ip)
    new_data.save()

    # --- Update SevenDayData ---
    record, created = SevenDayData.objects.get_or_create(
        id=1,  # global; later you can tie this to url_details if you want per-link tracking
        defaults={
            "day1_date": today,
            "day1_value": str(url_to_edit.number_of_times_clicked),
        }
    )

    # Shift data forward and add today’s new click count
    record.shift_days(str(url_to_edit.number_of_times_clicked))

    return redirect(url_details.long_link)


# function to generate graph so we can analyze our number of clicks
def generate_graph(request, pk):
    # getting the url and the click data for each url
    url_details = URLModel.objects.filter(uuid=pk).first()
    click_details = Click.objects.filter(url_relation__uuid=pk).first()

    if not url_details or not click_details:
        return render(request, "graph.html", {"error": "No data available yet."})

    # getting date and the click count
    date_clicked = click_details.time_clicked
    times_clicked = url_details.number_of_times_clicked

    # Updating the seven day data model
    record, created = SevenDayData.objects.get_or_create(
        id=1,
        defaults={
            "day1_date": date_clicked,
            "day1_value": str(times_clicked),
        }
    )

    # Shift and add today's data if record already exists
    record.shift_days(str(times_clicked))

    # Build data arrays for plotting
    dates = [
        record.day1_date, record.day2_date, record.day3_date,
        record.day4_date, record.day5_date, record.day6_date, record.day7_date
    ]
    values = [
        int(record.day1_value or 0), int(record.day2_value or 0), int(record.day3_value or 0),
        int(record.day4_value or 0), int(record.day5_value or 0), int(record.day6_value or 0),
        int(record.day7_value or 0)
    ]

    # --- Plot the graph ---
    plt.figure(figsize=(8, 5))
    plt.plot(dates, values, marker="o", linestyle="-", color="blue")
    plt.title("Weekly Click Analytics")
    plt.xlabel("Date")
    plt.ylabel("Clicks")
    plt.xticks(rotation=30)
    plt.tight_layout()

    # Convert plot to base64 so we can embed it in HTML
    buf = io.BytesIO()
    plt.savefig(buf, format="png")
    buf.seek(0)
    graph = base64.b64encode(buf.read()).decode("utf-8")
    buf.close()

    # Render your template (graph.html)
    return render(request, "graph.html", {
        "url": url_details,
        "graph": f"data:image/png;base64,{graph}",
    })

Basically I want each time I click a link I want it to save the number of times the link was clicked and save the date at which the particular link was clicked but while saving I get a null error, and with that error I cant also generate a weekly graph analyzing the number of clicks so in summary I want to save daily amount of clicks for seven days but I have a null error

1 Answer 1

1

You here try to store None/NULL in the database for non-NULLable fields, you can make these NULLable with:

class SevenDayData(models.Model):
    day1_date = models.DateField(null=True, default=None)
    day1_value = models.CharField(null=True, max_length=20)

    day2_date = models.DateField(null=True, default=None)
    day2_value = models.CharField(null=True, max_length=20)

    day3_date = models.DateField(null=True, default=None)
    day3_value = models.CharField(null=True, max_length=20)

    day4_date = models.DateField(null=True, default=None)
    day4_value = models.CharField(null=True, max_length=20)

    day5_date = models.DateField(null=True, default=None)
    day5_value = models.CharField(null=True, max_length=20)

    day6_date = models.DateField(null=True, default=None)
    day6_value = models.CharField(null=True, max_length=20)

    day7_date = models.DateField(null=True, default=None)
    day7_value = models.CharField(null=True, max_length=20)

    # updating the model each time the row is saved
    updated_at = models.DateTimeField(auto_now=True)

But, a model should not be concerned how to enter data, it should focus on how to store data. You just store single entries, like:

class DayData(models.Model):
    day_date = models.DateField()
    day_value = models.CharField(max_length=20)

so you insert single data.

In case you want to retrieve then data from the last seven days, you can query with:

DayData.objects.filter(day_date__gte=datetime.now().date()-timedelta(days=7))

or if you want the last seven entries with:

DayData.objects.order_by('-day_date')[:7]
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.