76
votes

For a Django App, each "member" is assigned a color to help identify them. Their color is stored in the database and then printed/copied into the HTML when it is needed. The only issue is that I am unsure how to generate random Hex colors in python/django. It's easy enough to generate RGB colors, but to store them I would either need to a) make three extra columns in my "Member" model or b) store them all in the same column and use commas to separate them, then, later, parse the colors for the HTML. Neither of these are very appealing, so, again, I'm wondering how to generate random Hex colors in python/django.

16

16 Answers

151
votes
import random
r = lambda: random.randint(0,255)
print('#%02X%02X%02X' % (r(),r(),r()))
50
votes

Here is a simple way:

import random
color = "%06x" % random.randint(0, 0xFFFFFF)

To generate a random 3 char color:

import random
color = "%03x" % random.randint(0, 0xFFF)

%x in C-based languages is a string formatter to format integers as hexadecimal strings while 0x is the prefix to write numbers in base-16.

Colors can be prefixed with "#" if needed (CSS style)

10
votes

Store it as a HTML color value:

Updated: now accepts both integer (0-255) and float (0.0-1.0) arguments. These will be clamped to their allowed range.

def htmlcolor(r, g, b):
    def _chkarg(a):
        if isinstance(a, int): # clamp to range 0--255
            if a < 0:
                a = 0
            elif a > 255:
                a = 255
        elif isinstance(a, float): # clamp to range 0.0--1.0 and convert to integer 0--255
            if a < 0.0:
                a = 0
            elif a > 1.0:
                a = 255
            else:
                a = int(round(a*255))
        else:
            raise ValueError('Arguments must be integers or floats.')
        return a
    r = _chkarg(r)
    g = _chkarg(g)
    b = _chkarg(b)
    return '#{:02x}{:02x}{:02x}'.format(r,g,b)

Result:

In [14]: htmlcolor(250,0,0)
Out[14]: '#fa0000'

In [15]: htmlcolor(127,14,54)
Out[15]: '#7f0e36'

In [16]: htmlcolor(0.1, 1.0, 0.9)
Out[16]: '#19ffe5'
8
votes

This has been done before. Rather than implementing this yourself, possibly introducing errors, you may want to use a ready library, for example Faker. Have a look at the color providers, in particular hex_digit.

In [1]: from faker import Factory

In [2]: fake = Factory.create()

In [3]: fake.hex_color()
Out[3]: u'#3cae6a'

In [4]: fake.hex_color()
Out[4]: u'#5a9e28'
6
votes

little late to the party,

import random
chars = '0123456789ABCDEF'
['#'+''.join(random.sample(chars,6)) for i in range(N)]
4
votes

Just store them as an integer with the three channels at different bit offsets (just like they are often stored in memory):

value = (red << 16) + (green << 8) + blue

(If each channel is 0-255). Store that integer in the database and do the reverse operation when you need to get back to the distinct channels.

4
votes
import random

def hex_code_colors():
    a = hex(random.randrange(0,256))
    b = hex(random.randrange(0,256))
    c = hex(random.randrange(0,256))
    a = a[2:]
    b = b[2:]
    c = c[2:]
    if len(a)<2:
        a = "0" + a
    if len(b)<2:
        b = "0" + b
    if len(c)<2:
        c = "0" + c
    z = a + b + c
    return "#" + z.upper()
3
votes

So many ways to do this, so here's a demo using "colorutils".

pip install colorutils

It is possible to generate random values in (RGB, HEX, WEB, YIQ, HSV).

# docs and downloads at 
# https://pypi.python.org/pypi/colorutils/

from colorutils import random_web
from tkinter import Tk, Button

mgui = Tk()
mgui.geometry('150x28+400+200')


def rcolor():
    rn = random_web()
    print(rn)  # for terminal watchers
    cbutton.config(text=rn)
    mgui.config(bg=rn)


cbutton = Button(text="Click", command=rcolor)
cbutton.pack()

mgui.mainloop()

I certainly hope that was helpful.

2
votes

For generating random anything, take a look at the random module

I would suggest you use the module to generate a random integer, take it's modulo 2**24, and treat the top 8 bits as R, that middle 8 bits as G and the bottom 8 as B.
It can all be accomplished with div/mod or bitwise operations.

2
votes
import random

def generate_color():
    color = '#{:02x}{:02x}{:02x}'.format(*map(lambda x: random.randint(0, 255), range(3)))
    return color
2
votes

Basically, this will give you a hashtag, a randint that gets converted to hex, and a padding of zeroes.

from random import randint
color = '#{:06x}'.format(randint(0, 256**3))
#Use the colors wherever you need!
1
votes
hex_digits = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']

digit_array = []

for i in xrange(6):
    digit_array.append(hex_digits[randint(0,15)])
joined_digits = ''.join(digit_array)

color = '#' + joined_digits
0
votes
import random

def get_random_hex:
    random_number = random.randint(0,16777215)

    # convert to hexadecimal
    hex_number = str(hex(random_number))

    # remove 0x and prepend '#'
    return'#'+ hex_number[2:]
0
votes

Would like to improve upon this solution as I found that it could generate color codes that have less than 6 characters. I also wanted to generate a function that would create a list that can be used else where such as for clustering in matplotlib.

import random

def get_random_hex:
    random_number = random.randint(0,16777215)

    # convert to hexadecimal
    hex_number = str(hex(random_number))

    # remove 0x and prepend '#'
    return'#'+ hex_number[2:]

My proposal is :

import numpy as np 

def color_generator (no_colors):
    colors = []
    while len(colors) < no_colors:
        random_number = np.random.randint(0,16777215)
        hex_number = format(random_number, 'x')
        if len(hex_number) == 6: 
            hex_number = '#'+ hex_number
            colors.append (hex_number)
    return colors
0
votes

Here's a simple code that I wrote based on what hexadecimal color notations represent:

import random 

def getRandomCol():
    
    r = hex(random.randrange(0, 255))[2:]
    g = hex(random.randrange(0, 255))[2:]
    b = hex(random.randrange(0, 255))[2:]

    random_col = '#'+r+g+b
    return random_col

The '#' in the hexadecimal color code just represents that the number represented is just a hexadecimal number. What's important is the next 6 digits. Pairs of 2 digits in those 6 hexadecimal digits represent the intensity of RGB (Red, Green, and Blue) each. The intensity of each color ranges between 0-255 and a combination of different intensities of RGB produces different colors.

For example, in #ff00ff, the first ff is equivalent to 255 in decimal, the next 00 is equivalent to 0 in decimal, and the last ff is equivalent to 255 in decimal. Therefore, #ff00ff in hexadecimal color coding is equivalent to RGB(255, 0, 255).

With this concept, here's the explanation of my approach:

  1. Generated intensities of random numbers for each of r, g and b
  2. Converted those intensities into hexadecimal
  3. Ignored the first 2 characters of each hexadecimal value '0x'
  4. Concatenated '#' with the hexadecimal values r, g and b intensities.

Feel free to refer to this link if you wanna know more about how colors work: https://hackernoon.com/hex-colors-how-do-they-work-d8cb935ac0f

Cheers!

0
votes
import secrets
rgba = '#'+secrets.token_hex(3)